home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / delicious_bookmarks-2.0.64-fx.xpi / chrome / deliciousBookmarks.jar / content / ybSidebarOverlay.xml < prev    next >
Encoding:
Extensible Markup Language  |  2008-06-19  |  127.2 KB  |  2,880 lines

  1. <?xml version="1.0"?>
  2. <!DOCTYPE overlay SYSTEM "chrome://ybookmarks/locale/ybookmarks.dtd">
  3. <bindings
  4.    xmlns="http://www.mozilla.org/xbl"
  5.    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  6.      xmlns:rdf="http://home.netscape.com/NC-rdf#"
  7.      xmlns:html="http://www.w3.org/1999/xhtml"
  8.      xmlns:xbl="http://www.mozilla.org/xbl">
  9.     
  10.   <binding id="ybsidebar">
  11.       <resources>
  12.         <stylesheet src="chrome://ybookmarks/skin/overlay.css" />
  13.         <script src="chrome://ybookmarks/content/providerApis.js" type="application/x-javascript" />
  14.         <script src="chrome://ybookmarks/content/ybookmarksUtils.js" type="application/x-javascript" />
  15.       </resources>
  16.   
  17.      <implementation implements="nsIObserver, nsIRDFObserver">
  18.        <constructor>
  19.          <![CDATA[
  20.                  
  21.            ybookmarksUtils.importSymbols(this,
  22.                                          "gRdfService", "gRdfContainerUtils", "addObserver", "removeObserver",
  23.                                          "nsIRDFLiteral",
  24.                                          "bookmarkResource",
  25.                                          "grscTag", "grscTagValue", "grscChildCount", "grscTagRoot", "grscBookmarksRoot", 
  26.                                          "grscName", "grscDesc", "grscShortcut", "grscShared", "grscType", "grscBookmarkType", "grscLivemarkType", 
  27.                                          "grscUrl", "grscVisitCount", "grscLastVisitDate", "grscAddDate", "grscIcon");
  28.            
  29.            const nsIRDFLiteral        = Components.interfaces.nsIRDFLiteral;
  30.            const nsIRDFDate           = Components.interfaces.nsIRDFDate;
  31.            const nsIRDFInt            = Components.interfaces.nsIRDFInt;
  32.  
  33.            var bookmarksStore         = this.bookmarksStore;
  34.            var bookmarksDatasource    = this.bookmarksDatasource;
  35.            var searchDatasource       = this.searchDatasource;
  36.  
  37.            var tagsTree               = this.tagsTree           = this.getElementByAnonid("ybbookmarks-tree-tags"); 
  38.            var bookmarksTree          = this.bookmarksTree      = this.getElementByAnonid("ybbookmarks-tree-bookmarks");
  39.            var tagsSortMenu           = this.tagsSortMenu       = this.getElementByAnonid("ybsidebar-tags-sort-menu");
  40.            var tagsCount              = this.tagsCount          = this.getElementByAnonid("ybsidebar-tags-count");
  41.            var bookmarksSortMenu      = this.bookmarksSortMenu  = this.getElementByAnonid("ybsidebar-bookmarks-sort-menu");
  42.            var bookmarksCount         = this.bookmarksCount     = this.getElementByAnonid("ybsidebar-bookmarks-count");
  43.                
  44.            var enumeratorMap          = ybookmarksUtils.enumeratorMap; // import function into scope           
  45.    
  46.            yDebug.print("$Name: del2alpha $; $Id: //DeliciousXT/Main/FFXT/del2alpha/content/ybSidebarOverlay.xml#7 $");
  47.  
  48.            const theXBL = this;
  49.            
  50.            /******************************************************************************
  51.  
  52.                 Tag object
  53.  
  54.             ******************************************************************************/
  55.  
  56.            function Tag(name, parent, isDirty) {
  57.                this.Name    = name;
  58.                this.parent  = parent;
  59.                this.Level   = parent ? parent.Level + 1 : 0;
  60.                this.isDirty = isDirty ? isDirty : false;
  61.            }
  62.  
  63.            Tag.prototype.memoizeGetter = ybookmarksUtils.memoizeGetter;
  64.            Tag.getNameFromResource = function(tagResource) { 
  65.                return ybookmarksUtils.getValue(bookmarksDataSource, tagResource, grscTagValue, nsIRDFLiteral); 
  66.            };
  67.            Tag.getAll = function Tag__getAll() {
  68.                var tagsEnumerator = gRdfContainerUtils.MakeSeq(bookmarksDataSource, grscTagRoot).GetElements();
  69.                return enumeratorMap(tagsEnumerator, function(tagResource) {
  70.                    var tagName = Tag.getNameFromResource(tagResource);
  71.                    if (bookmarksStore.getTotalBookmarksForTag(tagName) > 0) {
  72.                        return new Tag(tagName);
  73.                    } 
  74.                });
  75.            }
  76.  
  77.            Tag.prototype.getAncestors = function() {
  78.                var result = [];
  79.                for (var tag = this; tag != null; tag = tag.parent) { result[result.length] = tag; }
  80.                return result;
  81.            }
  82.  
  83.            Tag.prototype.getRelatedTags = function() {
  84.                var tagsSet = {}, relatedTags = [], tagName = this.Name;
  85.  
  86.                this.bookmarks.forEach(function(bookmark) {
  87.                    bookmark.tags.forEach( function(tag) { tagsSet[tag.toLowerCase()] = true; } );
  88.                });
  89.                for (var k in tagsSet) {
  90.                    if (tagsSet.hasOwnProperty(k) && k != tagName) {
  91.                        relatedTags[relatedTags.length] = new Tag(k, this);
  92.                    }
  93.                }
  94.  
  95.                return relatedTags;
  96.            }
  97.  
  98.            Tag.prototype.matchesSearchQuery = function(searchQuery) {
  99.                var keywords;
  100.                if (searchQuery.indexOf('+') != -1) return false;
  101.                keywords = searchQuery.split(' ');
  102.                return ybookmarksUtils.searchStringForKeywords(this.Name, keywords);
  103.            };
  104.  
  105.            Tag.prototype.memoizeGetter("NumBookmarks", function() { 
  106.                return this.Level ? getBookmarksForTags(this.getAncestors()).length : bookmarksStore.getTotalBookmarksForTag(this.Name);
  107.            });
  108.  
  109.            Tag.prototype.memoizeGetter("bookmarks", function() {
  110.                try {
  111.                  var tagLiteral            = gRdfService.GetLiteral(this.Name);
  112.                  var tagResource           = bookmarksDataSource.GetSource(grscTagValue, tagLiteral, true);
  113.                  var bookmarksEnumerator   = gRdfContainerUtils.MakeSeq(bookmarksDataSource, tagResource).GetElements();
  114.                
  115.                  return enumeratorMap(bookmarksEnumerator, Bookmark.getNew);
  116.                } catch (e) {
  117.                  yDebug.print("Tag.bookmarks getter: Failed to get bookmarks for tag: " + this.Name);
  118.                  return [];
  119.                }
  120.            });
  121.  
  122.  
  123.            /******************************************************************************
  124.  
  125.                 Bookmark object
  126.  
  127.             ******************************************************************************/
  128.  
  129.            function Bookmark(resource, parent, isDirty) {
  130.                this.resource = resource;
  131.                this.parent   = parent;
  132.                this.Level    = parent ? parent.Level + 1 : 0;
  133.                this.isDirty = isDirty ? isDirty : false;
  134.            }
  135.            Bookmark.prototype.getValue = function(pred, iface) {
  136.                var val = bookmarksDataSource.GetTarget(this.resource, pred, true);
  137.                return val ? val.QueryInterface(iface).Value : 0;
  138.            }
  139.            Bookmark.prototype.memoizeGetter = ybookmarksUtils.memoizeGetter;
  140.            Bookmark.getAll = function() {
  141.                var bookmarksRoot = gRdfContainerUtils.MakeSeq(bookmarksDataSource, grscBookmarksRoot).GetElements();
  142.                return enumeratorMap(bookmarksRoot, Bookmark.getNew);
  143.            }
  144.  
  145.            Bookmark.prototype.memoizeGetter("Name", 
  146.                                             function() { return this.getValue(grscName, nsIRDFLiteral); });
  147.            Bookmark.prototype.memoizeGetter("url", 
  148.                                             function() { return this.getValue(grscUrl, nsIRDFLiteral); });
  149.            Bookmark.prototype.memoizeGetter("shortcut", 
  150.                                             function() { return this.getValue(grscShortcut, nsIRDFLiteral) || ""; });
  151.            Bookmark.prototype.memoizeGetter("icon", 
  152.                                             function() { return this.getValue(grscIcon, nsIRDFLiteral); });
  153.            Bookmark.prototype.memoizeGetter("desc", 
  154.                                             function() { return this.getValue(grscDesc, nsIRDFLiteral); });
  155.            Bookmark.prototype.memoizeGetter("shared", 
  156.                                             function() { return "true" === this.getValue(grscShared, nsIRDFLiteral); });
  157.            Bookmark.prototype.memoizeGetter("last_visited", 
  158.                                             function() { return this.getValue(grscLastVisitDate, nsIRDFDate) / 1000000 || this.added_date; });
  159.            Bookmark.prototype.memoizeGetter("added_date", 
  160.                                             function() { return this.getValue(grscAddDate, nsIRDFDate) / 1000000 || 0; });
  161.            Bookmark.prototype.memoizeGetter("visit_count", 
  162.                                             function() { return this.getValue(grscVisitCount, nsIRDFInt); });
  163.            Bookmark.prototype.memoizeGetter("tags", 
  164.                function() {
  165.                    var tagsEnumerator = bookmarksDataSource.GetTargets(this.resource, grscTag, true);
  166.                    return enumeratorMap(tagsEnumerator, 
  167.                       function(tagResource) { return tagResource.QueryInterface(nsIRDFLiteral).Value.toLowerCase() });
  168.                }
  169.            );
  170.            Bookmark.prototype.isLivemark = function() {
  171.                return "Livemark" === bookmarksStore.resolveBookmarkResourceType(this.resource);
  172.            },
  173.            Bookmark.prototype.getLivemarkChildren = function() {
  174.                if (this.isLivemark()) {
  175.                    var livemarkContainer = gRdfContainerUtils.MakeSeq(bookmarksDataSource, this.resource);
  176.                    var theBookmark = this;
  177.                    return enumeratorMap(livemarkContainer.GetElements(), function(feedItem) {
  178.                        return new Bookmark(feedItem, theBookmark);
  179.                    });
  180.                } else {
  181.                    return [];
  182.                }
  183.            },
  184.            Bookmark.prototype.hasTags = function(tagArray) {
  185.                var tags = this.tags;
  186.                for (var i = tagArray.length - 1; i >= 0; i--) {
  187.                    if (tags.indexOf(tagArray[i].Name) < 0) {
  188.                        return false;
  189.                    }
  190.                }
  191.                return true;
  192.            }
  193.            Bookmark.prototype.matchesSearchQuery = function(searchQuery) {
  194.                   var tags = this.tags;
  195.                   var tagCloud = "";
  196.                var conjunction = true;
  197.                var keywords = searchQuery.split('+');
  198.                if (keywords.length === 1) {
  199.                    keywords = searchQuery.split(' ');
  200.                    conjuction = false;
  201.                }
  202.                
  203.                for (var i=0; i<tags.length; i++) {
  204.                           tagCloud += tags[i] + " ";
  205.                   }
  206.                
  207.                return ybookmarksUtils.searchStringForKeywords(tagCloud, keywords, conjunction) ||
  208.                          ybookmarksUtils.searchStringForKeywords(this.Name, keywords, conjunction) ||
  209.                       ybookmarksUtils.searchStringForKeywords(this.url, keywords, conjunction)  ||
  210.                       ybookmarksUtils.searchStringForKeywords(this.desc, keywords, conjunction) ||
  211.                       ybookmarksUtils.searchStringForKeywords(this.shortcut, keywords, conjunction);
  212.            };
  213.  
  214.  
  215.            /*
  216.             * These functions wrap the constructor so that it can be used in an Array.map call
  217.             */
  218.            Tag.getNew       = function(arg) { return new Tag(arg); }
  219.            Bookmark.getNew  = function(arg) { return new Bookmark(arg); }
  220.  
  221.            /**
  222.             **  Get an array of bookmarks that have ALL of the tags in aTagArray
  223.             **
  224.             **  @param aTagArray an array of strings representing tag names
  225.             **/
  226.            function getBookmarksForTags(aTagArray) {
  227.                var head = aTagArray[0];
  228.  
  229.                if (!aTagArray || !aTagArray.length) {
  230.                    return Bookmark.getAll();
  231.                } else if (aTagArray.length == 1) {
  232.                    return head.bookmarks;
  233.                } else {
  234.                    /**
  235.                     **  Recursive calculation of intersection; tip of the hat to Lisp :-)
  236.                     **/
  237.  
  238.                    var bookmarks_car = head.bookmarks;
  239.                    var bookmarks_cdr = getBookmarksForTags(aTagArray.slice(1));
  240.                    var i, j, results = [];
  241.  
  242.                outerLoop:
  243.                    for (i = bookmarks_car.length - 1; i >= 0; i--) {
  244.                        var bookmark = bookmarks_car[i];
  245.                        var resource1 = bookmark.resource;
  246.                    innerLoop:
  247.                        for (j = bookmarks_cdr.length - 1; j >= 0; j--) {
  248.                            if (bookmarks_cdr[j].resource == resource1) {
  249.                                results[results.length] = bookmark;
  250.                                continue outerLoop;
  251.                            }
  252.                        }
  253.                    }
  254.  
  255.                    /*----------------------------------------------------
  256.                      Hmmm, using the Array.filter and Array.some functions
  257.                      seems to be SLOWER than rolling my own loops. :-)
  258.  
  259.                      var results = bookmarks_car.filter
  260.                        ( function(x) { 
  261.                            var x_resource = x.resource;
  262.                            return bookmarks_cdr.some( function(y) { 
  263.                                return y.resource == x_resource; 
  264.                            } ); 
  265.                        } );
  266.                      --------------------------------------------------*/
  267.  
  268.                    return results;
  269.                }
  270.            }
  271.  
  272.            function getComparatorFunc(property) {
  273.                switch (property) {
  274.                    case "Name":           return function nameComparator(n1, n2) {
  275.                        var name1 = n1.Name.toLowerCase(), name2 = n2.Name.toLowerCase();
  276.                        return (name1 < name2) ? -1 : (name1 > name2) ? 1 : getComparatorFunc("url")(n1, n2);
  277.                    };
  278.                    case "url":            return function urlComparator(n1, n2) {
  279.                        var url1 = n1.url, url2 = n2.url;
  280.                        return (url1 < url2) ? -1 : (url1 > url2) ? 1 : 0;
  281.                    };
  282.                    case "resourceUri":    return function resourceComparator(n1, n2) {
  283.                        var uri1 = n1.resource.Value, uri2 = n2.resource.Value;
  284.                        return (uri1 < uri2) ? -1 : (uri1 > uri2) ? 1 : 0;
  285.                    };
  286.                    case "NumBookmarks":   return function numBookmarksComparator(n1, n2) { 
  287.                        var numBooks_diff = n2.NumBookmarks - n1.NumBookmarks; 
  288.                        return numBooks_diff != 0 ? numBooks_diff : getComparatorFunc("Name")(n1, n2);
  289.                    };
  290.                    case "last_visited":   return function lastVisitedComparator(n1, n2) { 
  291.                        return n2.last_visited - n1.last_visited; 
  292.                    };
  293.                    case "added_date":   return function addedDateComparator(n1, n2) { 
  294.                        return n2.added_date - n1.added_date; 
  295.                    };
  296.                    case "visit_count":    return function visitCountComparator(n1, n2) { 
  297.                        var visit_count_diff = n2.visit_count - n1.visit_count; 
  298.                        return visit_count_diff != 0 ? visit_count_diff : getComparatorFunc("Name")(n1, n2);
  299.                    };
  300.                    default:               return null;
  301.                }
  302.            }
  303.  
  304.  
  305.            /******************************************************************************
  306.  
  307.                 CustomTreeView
  308.  
  309.             ******************************************************************************/
  310.  
  311.            function CustomTreeView(props) {
  312.                this.addProperties(props);
  313.                this.table = [];
  314.                this.__defineGetter__("rowCount", function() { return this.table.length; });
  315.            }
  316.            var methods = {
  317.                addProperties          : function(props)            { for (var p in props) this[p] = props[p]; },
  318.                setData                : function(data)             { this.data = data; this.loadTable(); },
  319.                updateCount            : function()                 { this.countElem.value = this.rowCount; },
  320.                setTree                : function(treebox)          { 
  321.                    if (treebox && treebox !== this.treebox) {         // This check prevents loads from happening on exit
  322.                        this.treebox = treebox; 
  323.                        this.loadTable(); 
  324.                        if (this.initFunction) this.initFunction();
  325.                    }
  326.                },
  327.                listenForEvent         : function(elem, eventName, handlerFunc) {
  328.                    var self = this;
  329.                    eventHandler = function() { return self[handlerFunc](); };
  330.                    return elem.addEventListener(eventName, eventHandler, true);
  331.                },
  332.                hasNextSibling         : function(row, afterIndex) {   // Note: Called on Windows; not Mac
  333.                    var thisLevel = this.getLevel(row);
  334.                    var rowCount = this.rowCount;
  335.                    for (var t = afterIndex + 1; t < rowCount; t++) {
  336.                        var nextLevel = this.getLevel(t);
  337.                        if (nextLevel == thisLevel) return true;
  338.                        else if (nextLevel < thisLevel) return false;
  339.                    }
  340.                    return false;
  341.                },
  342.                getNumChildren : function(row) {
  343.                    var row2 = row + 1, rowCount = this.rowCount, level = this.getLevel(row);
  344.                    while (row2 < rowCount && this.getLevel(row2) > level) {
  345.                        ++row2;
  346.                    }
  347.                    return row2 - row - 1;
  348.                },
  349.                linearSearch           : function(fn) {
  350.                    return ybookmarksUtils.linearSearch(this.table, fn);
  351.                },
  352.                getRowByName           : function(name) {
  353.                    return this.linearSearch(function(x) { return x.Name == name; });
  354.                },
  355.                getRowByResourceUri    : function(resourceUri) {
  356.                    return this.linearSearch(function(x) { return x.resource.Value == resourceUri; });
  357.                },
  358.                invalidateRow          : function(row) {
  359.                    this.treebox.invalidateRow(row);
  360.                },
  361.                addNodes               : function(row, nodes) {
  362.                    this.table = ybookmarksUtils.arraySplice(this.table, row, nodes);
  363.                    this.treebox.rowCountChanged(row, +nodes.length);
  364.                },
  365.                addNode                : function(row, node) {
  366.                    this.table.splice(row, 0, node);
  367.                    this.treebox.rowCountChanged(row, +1);
  368.                },
  369.                deleteNodes            : function(row, count) {
  370.                    this.table.splice(row, count);
  371.                    this.treebox.rowCountChanged(row, -count);
  372.                },
  373.                deleteNode             : function(row) {
  374.                    this.table.splice(row, 1);
  375.                    this.treebox.rowCountChanged(row, -1);
  376.                },
  377.                closeNode              : function(row) {
  378.                    this.deleteNodes(row + 1, this.getNumChildren(row));
  379.                    this.table[row].isOpen = false;
  380.                },
  381.                openNode               : function(row) {
  382.                    var node = this.table[row];
  383.                    var childrenToInsert  = this.data.getNodes(node, this.getComparator()).map(function(x) { x.parentIndex = row; return x; });
  384.                    this.addNodes(row + 1, childrenToInsert);
  385.                    this.table[row].isOpen = true;
  386.                },
  387.                toggleOpenState        : function(row) {
  388.                    if (this.getLevel(row) > 0) return;
  389.                    if (this.isContainerOpen(row)) {
  390.                        this.closeNode(row);
  391.                    } else {
  392.                        this.openNode(row);
  393.                    }
  394.                    this.treebox.invalidateRow(row);
  395.                },
  396.                closeOpenedNodes       : function() {
  397.                    var openedNodes = [];
  398.                    for (var i = this.rowCount - 1; i >= 0; i--) {
  399.                        if (this.table[i].isOpen) {
  400.                            openedNodes[openedNodes.length] = this.table[i];
  401.                            this.closeNode(i);
  402.                        }
  403.                    }
  404.                    return openedNodes;
  405.                },
  406.                openNodes              : function(nodes) {
  407.                    for (var i = nodes.length - 1; i >= 0; i--) {
  408.                        var row = this.getRowByName(nodes[i].Name);
  409.                        if (row >= 0) {
  410.                            this.openNode(row);
  411.                        }
  412.                    }
  413.                },
  414.                loadTable              : function() {
  415.                    var oldRowCount = this.rowCount;
  416.                    this.table = this.data.getNodes();
  417.                    this.treebox.rowCountChanged(0, this.rowCount - oldRowCount);
  418.                    this.treebox.invalidate();
  419.                    this.updateCount();
  420.                    return this;
  421.                },
  422.                getSelectedNode        : function() {
  423.                    var selectedIndex = this.selection ? this.selection.currentIndex : -1;
  424.                    return selectedIndex >= 0 ? this.table[selectedIndex] : null;
  425.                },
  426.                nodeMatches            : function(aPrimaryNode, aSecondaryNode) {
  427.                    if (aPrimaryNode.Name !== aSecondaryNode.Name) {
  428.                        return false;
  429.                    } else if (aPrimaryNode.parent && aPrimaryNode.parent !== aSecondaryNode.parent) {
  430.                        return false;
  431.                    } else {
  432.                        return true;
  433.                    }
  434.                },
  435.                nodeFiltered         : function(node) {
  436.                    return this.data.containsNode && !this.data.containsNode(node);
  437.                },
  438.                clearSelection         : function() {
  439.                    this.selection.clearSelection();
  440.                    this.selection.currentIndex = -1;
  441.                },
  442.                selectNode             : function(aNode) {
  443.                    for (var i = this.rowCount - 1; i >= 0; i--) {
  444.                        if (this.nodeMatches(aNode, this.table[i])) {
  445.                            this.selection.select(i);
  446.                            this.treebox.ensureRowIsVisible(i);
  447.                        }
  448.                    }
  449.                },
  450.                getComparator          : function() {
  451.                    var col = this.sortMenuItemMap[this.getComparatorKey()];
  452.                    return getComparatorFunc(col);
  453.                },
  454.                sortTable              : function sortTable() { 
  455.                    /*
  456.                     *  Remember the currently selected node so we can restore it after the sort
  457.                     */
  458.                    var selectedNodeBeforeSort = this.getSelectedNode();
  459.  
  460.                    /*
  461.                     *  Close any open nodes, remembering them so that they can be reopened afterwards.
  462.                     *  Closing is required because open nodes break the sort order
  463.                     */
  464.                    var nodesOpenedBeforeSort = this.closeOpenedNodes();
  465.  
  466.                    var comparator = this.getComparator();
  467.                    if (comparator) {
  468.                        yDebug.print("******************* sorting table of length:" + this.table.length);
  469.                        this.table = this.table.sort(comparator);
  470.                    }
  471.                    for (var i = 0; i < this.table.length; ++i) {
  472.                         this.table[i].isDirty = false;
  473.                    }
  474.                    this.openNodes(nodesOpenedBeforeSort);
  475.                    if (selectedNodeBeforeSort) {
  476.                         if (theXBL._popupShowing) { // sidebar or popup currently visible
  477.                             this.selectNode(selectedNodeBeforeSort);
  478.                         }
  479.                    }
  480.                    this.treebox.invalidate();
  481.                },
  482.                mergeTable              : function mergeTable() { 
  483.                    /*
  484.                     *  Remember the currently selected node so we can restore it after the sort
  485.                     */
  486.                    var selectedNodeBeforeSort = this.getSelectedNode();
  487.  
  488.                    /*
  489.                     *  Close any open nodes, remembering them so that they can be reopened afterwards.
  490.                     *  Closing is required because open nodes break the sort order
  491.                     */
  492.                    var nodesOpenedBeforeSort = this.closeOpenedNodes();
  493.  
  494.                    var comparator = this.getComparator();
  495.                    if (comparator) {
  496.                        var tTable = new Array();
  497.                        for (var i = 0; i < this.table.length; ++i) {
  498.                             var obj  = this.table[i];
  499.                             if (obj.isDirty) {
  500.                                 obj.isDirty = false;
  501.                                 tTable[tTable.length] = obj;
  502.                                 this.table.splice(i, 1);
  503.                             }
  504.                        }
  505.                        if (tTable.length <= 0) {
  506.                             return;
  507.                        }
  508.                        tTable.sort(comparator);
  509.                        
  510.                        var tableIndex = this.table.length - 1;
  511.                        var tTableIndex = tTable.length - 1;
  512.                        for (var mergedTableIndex = this.table.length + tTable.length - 1; mergedTableIndex >= 0; --mergedTableIndex) {
  513.                             if (tableIndex < 0) { // table exhausted
  514.                                 this.table[mergedTableIndex] = tTable[tTableIndex];
  515.                                 --tTableIndex;
  516.                                 continue;
  517.                             }
  518.                             if (tTableIndex < 0) { // tTable exhausted
  519.                                 this.table[mergedTableIndex] = this.table[tableIndex];
  520.                                 --tableIndex;
  521.                                 continue;
  522.                             }
  523.                             var rv = comparator(this.table[tableIndex], tTable[tTableIndex]);
  524.                             if (rv >= 0) {
  525.                                 this.table[mergedTableIndex] = this.table[tableIndex];
  526.                                 --tableIndex;
  527.                                 continue;                            
  528.                             } else {
  529.                                 this.table[mergedTableIndex] = tTable[tTableIndex];
  530.                                 --tTableIndex;
  531.                                 continue;
  532.                             } 
  533.                        }
  534.                    }
  535.                    this.openNodes(nodesOpenedBeforeSort);
  536.                    if (selectedNodeBeforeSort) {
  537.                         if (theXBL._popupShowing) { // sidebar or popup currently visible
  538.                             this.selectNode(selectedNodeBeforeSort);
  539.                         }
  540.                    }
  541.                    this.treebox.invalidate();
  542.                },
  543.                isContainer            : function(row)              { return true; },
  544.                isContainerEmpty       : function(row)              { return this.table[row].parentIndex >= 0; },
  545.                isContainerOpen        : function(row)              { return this.table[row].isOpen; },
  546.                isSeparator            : function(row)              { return false; },
  547.                isSorted               : function(row)              { return false; },
  548.                getCellText            : function(row, col)         { return this.table[row][col.id]; },
  549.                getParentIndex         : function(row)              { return this.table[row].parentIndex || -1; },
  550.                getImageSrc            : function(row, col)         { return this.table[row].icon; },
  551.                getLevel               : function(row)              { return this.table[row].Level; },
  552.                getRowProperties       : function(row, props)       {},
  553.                getColumnProperties    : function(col, props)       {},
  554.                getCellProperties      : function(row, col, props)  {}
  555.            };
  556.            methods.addProperties.call(CustomTreeView.prototype, methods);
  557.  
  558.  
  559.            this.tagsTreeData = {
  560.                getNodes      : function(tag, comparator) { 
  561.                    var nodes = tag ? tag.getRelatedTags() : Tag.getAll(); 
  562.                    if (comparator) {
  563.                        nodes = nodes.sort(comparator);
  564.                    }
  565.                    return nodes;
  566.                },
  567.                containsNode  : function(tag) { 
  568.                    return tag.NumBookmarks > 0; 
  569.                }
  570.            };
  571.  
  572.            this.tagsTreeDataSearch = function(storeNumber, searchQuery) {
  573.                return {
  574.                    searchQuery   : searchQuery.toLowerCase(),
  575.                    getNodes      : function(tag, comparator)  { 
  576.                        var nodes = tag ? tag.getRelatedTags() 
  577.                                        : bookmarksStore.getTagsSearchResults(storeNumber, {}).map(Tag.getNew);
  578.                        if (comparator) {
  579.                            nodes = nodes.sort(comparator);
  580.                        }
  581.                        return nodes;
  582.                    },
  583.                    containsNode  : function(tag) {
  584.                        return tag.NumBookmarks > 0 && tag.matchesSearchQuery(this.searchQuery);
  585.                    }
  586.                };
  587.            };
  588.  
  589.  
  590.            /******************************************************************************
  591.  
  592.                 tagsTreeView
  593.  
  594.             ******************************************************************************/
  595.            this.tagsTreeView = this.tagsTree.view = new CustomTreeView({
  596.                data                 : this.tagsTreeData, 
  597.                defaultComparator    : getComparatorFunc("Name"),
  598.                countElem            : tagsCount, 
  599.                getCellValue         : function()           { return "_yb_tag_entity"; }, // required for context menu
  600.                getComparatorKey     : function()           { return tagsSortMenu.selectedItem.id; },
  601.                sortMenuItemMap      : {
  602.                    "ybsidebar-tags-sort-menu-alpha"        : "Name",
  603.                    "ybsidebar-tags-sort-menu-freq"         : "NumBookmarks"
  604.                },
  605.                initFunction         : function() {
  606.                    this.listenForEvent(tagsSortMenu, "ValueChange", "sortTable");
  607.                    tagsSortMenu.addEventListener("ValueChange", 
  608.                                                   function (event) { theXBL._onSortSelect(event); }, 
  609.                                                   false);
  610.                    if (tagsSortMenu.selectedItem) this.sortTable();
  611.                },
  612.                updateTag            : function(tagName, operation) {
  613.                    var row = this.getRowByName(tagName), tag = null;
  614.                    var tag = new Tag(tagName, null, true);
  615.                    if (row >= 0) {
  616.                        if (this.nodeFiltered(tag)) {
  617.                             this.table.splice(row, 1);
  618.                        } else {
  619.                             this.table[row] = tag;
  620.                        }
  621.                    } else if ("assert" === operation) {
  622.                        if (!this.nodeFiltered(tag)) {
  623.                             this.table[this.table.length] = tag;
  624.                        }
  625.                    }
  626.                }
  627.            });
  628.  
  629.  
  630.            /******************************************************************************
  631.  
  632.                 bookmarksTreeView
  633.  
  634.             ******************************************************************************/
  635.  
  636.            this.bookmarksTreeData = {
  637.                getNodes      : function(livemark) {
  638.                    if (!livemark) {
  639.                        var tag = tagsTreeView.getSelectedNode();
  640.                        return tag ? getBookmarksForTags(tag.getAncestors()) : Bookmark.getAll();
  641.                    } else {
  642.                        return livemark.getLivemarkChildren();
  643.                    }
  644.                },
  645.                containsNode  : function(bookmark) {
  646.                    var tag = tagsTreeView.getSelectedNode();
  647.                    return tag ? bookmark.hasTags(tag.getAncestors()) : true;
  648.                }
  649.            };
  650.  
  651.            this.bookmarksTreeDataSearch = function(storeNumber, searchQuery) {
  652.                return {
  653.                    searchQuery  : searchQuery.toLowerCase(),
  654.                    getNodes     : function(livemark) { 
  655.                        if (!livemark) {
  656.                            var tag = tagsTreeView.getSelectedNode();
  657.                            return tag ? getBookmarksForTags(tag.getAncestors()) 
  658.                                       : bookmarksStore.getBookmarksSearchResults(storeNumber, {}).map(Bookmark.getNew);
  659.                        } else {
  660.                            return livemark.getLivemarkChildren();
  661.                        }
  662.                    },
  663.                    containsNode : function(bookmark) {
  664.                        var tag = tagsTreeView.getSelectedNode();
  665.                        if (tag) {
  666.                            return bookmark.hasTags(tag.getAncestors());
  667.                        }
  668.                        if (searchQuery.length > 0) {
  669.                            return bookmark.matchesSearchQuery(searchQuery);
  670.                        }
  671.                    }
  672.                };
  673.            };
  674.  
  675.           
  676.            this.bookmarksTreeView = this.bookmarksTree.view = new CustomTreeView({ 
  677.                data                 : this.bookmarksTreeData, 
  678.                defaultComparator    : getComparatorFunc("added_date"),
  679.                countElem            : bookmarksCount, 
  680.                isContainer          : function(row)        { return this.table[row].isLivemark(); },
  681.                getCellValue         : function(row, col)   { return this.table[row].url; },
  682.                onTagSelect          : function()           { this.loadTable(); this.sortTable(); },
  683.                getComparatorKey     : function()           { return bookmarksSortMenu.selectedItem.id; },
  684.                sortMenuItemMap      : {
  685.                    "ybsidebar-bookmarks-sort-menu-alpha"         : "Name",
  686.                    "ybsidebar-bookmarks-sort-menu-site"          : "url",
  687.                    "ybsidebar-bookmarks-sort-menu-most-visited"  : "visit_count",
  688.                    "ybsidebar-bookmarks-sort-menu-last-visited"  : "last_visited",
  689.                    "ybsidebar-bookmarks-sort-menu-last-added"    : "added_date"
  690.                },
  691.                getImageSrc            : function(row, col) { 
  692.                    if ("note" === col.id) {
  693.                        var bookmark = this.table[row];
  694.                        if (bookmark.desc && !bookmark.shared) {
  695.                            return "chrome://ybookmarks/skin/privateNote.gif";
  696.                        } else if (!bookmark.shared) {
  697.                            return "chrome://ybookmarks/skin/private.gif";
  698.                        } else if (bookmark.desc) {
  699.                            return "chrome://ybookmarks/skin/note.gif";
  700.                        }
  701.                    }
  702.                    if (!(this.table[row].isLivemark()) && "Name" === col.id) {
  703.                        var bookmark = this.table[row];
  704.                        if(bookmark && bookmark.icon) {
  705.                            return bookmark.icon;
  706.                        } 
  707.                    }
  708.                    return null;                   
  709.                },
  710.                getCellProperties    : function(row, col, props) {
  711.                    if (this.table[row].isLivemark()) {
  712.                        props.AppendElement(ybookmarksUtils.atomService.getAtom("livemark"));
  713.                    }
  714.                },
  715.                initFunction         : function() {
  716.                    this.listenForEvent(bookmarksSortMenu, "ValueChange", "sortTable");
  717.                    this.listenForEvent(tagsTree, "select", "onTagSelect");
  718.                    bookmarksSortMenu.addEventListener("ValueChange", 
  719.                                                   function (event) { theXBL._onSortSelect(event); }, 
  720.                                                   false);
  721.                    
  722.                    if (bookmarksSortMenu.selectedItem) this.sortTable();
  723.                },
  724.                getRowByUrl          : function(url) {
  725.                    return this.linearSearch(function(x) { return x.url == url; });
  726.                },
  727.                deleteBookmark       : function(url) {
  728.                    var row = this.getRowByUrl(url);
  729.                    if (row >= 0) {
  730.                        this.deleteNode(row);
  731.                    }
  732.                },
  733.                updateBookmark       : function(resourceUri, url) {
  734.                    var row = this.getRowByUrl(url), bookmark = null;
  735.                    var resource = gRdfService.GetResource(resourceUri);
  736.                    var bookmark = new Bookmark(resource, null, true);
  737.                    if (row >= 0) {
  738.                        if (this.nodeFiltered(bookmark)) {
  739.                             yDebug.print("Bookmark filtered " + url);
  740.                             this.table.splice(row, 1);
  741.                        } else {
  742.                             this.table[row] = bookmark;
  743.                        }
  744.                    } else {
  745.                        if ("LiveBookmark" !== bookmarksStore.resolveBookmarkResourceType(resource)) {
  746.                            if (!this.nodeFiltered(bookmark)) {
  747.                                 this.table[this.table.length] = bookmark;
  748.                            }
  749.                        }
  750.                    }
  751.                }
  752.                
  753.            });
  754.  
  755.            this.getElementByAnonid("ybsidebar-search-reset").addEventListener("click", function() { theXBL.reset(); }, false);           
  756.            
  757.            //set the login state
  758.            this._setLoginState();
  759.            
  760.            if (this.parentNode.nodeName == "popup") {        
  761.  
  762.              this._splitter.setAttribute("ybookmarkPopup", "true");
  763.                           
  764.              this._showSidebarButton.hidden = false;
  765.              this.enableSidebarSwitch(true);
  766.  
  767.              this.tagsSortMenu.collapsed = true;
  768.              this.bookmarksSortMenu.collapsed = true;
  769.              
  770.              this.tagsTree.removeAttribute("contextmenu");
  771.              this.bookmarksTree.removeAttribute("contextmenu");
  772.            }
  773.            
  774.            //set the last searched keyword
  775.            var keyword = this._getLastSidebarSearchValue();
  776.            if (keyword) {
  777.              this.search(keyword);
  778.              this.iconHandler(keyword);
  779.              this.setSearchBoxSelect();
  780.            }
  781.  
  782.            this.observedSubjects = ["ybookmark.userChanged",
  783.                                     "ybookmark.importBookmarks",
  784.                                     "ybookmark.syncBegin",
  785.                                     "ybookmark.syncDone",
  786.                                     "ybookmarkSearch.begin",
  787.                                     "ybookmarkSearch.end",
  788.                                     "ybookmarkSearch.inProgress",
  789.                                     "ybookmark.bookmarkDeleted"];
  790.            for (var i = 0; i < this.observedSubjects.length; i++) {
  791.                this.addObserver(this.observedSubjects[i]);
  792.            }
  793.            bookmarksDataSource.AddObserver(this);
  794.  
  795.            this._searchProgressMeter.hidden = true;
  796.                   
  797.           // set the sort orders
  798.           var bookmarksSortIndex = 0;
  799.           try {
  800.             bookmarksSortIndex = this._prefs.getIntPref("extensions.ybookmarks@yahoo.sidebar.bookmarksSortSelectedIndex");
  801.           } catch (e) { }
  802.           this.bookmarksSortMenu.selectedIndex = bookmarksSortIndex;
  803.  
  804.           var tagsSortIndex = 0;
  805.           try {
  806.             tagsSortIndex = this._prefs.getIntPref("extensions.ybookmarks@yahoo.sidebar.tagsSortSelectedIndex");
  807.           } catch (e) { }
  808.           this.tagsSortMenu.selectedIndex = tagsSortIndex;
  809.           
  810.           
  811.           // Below is a hack for the popup overlay
  812.           // apparently, if you mouseover a menulist (sort orders), they'll popup without a click
  813.           if (this.parentNode.nodeName == "popup") {
  814.  
  815.             var popupOnPopupShowing = function(event) {
  816.               if (this.yb_allowSortPopup) {
  817.                 this.menupopup.position = "after_start";
  818.               } else {
  819.                   event.preventDefault();    
  820.               }
  821.             };
  822.  
  823.             var popupOnClick = function(event) {
  824.               if (this.yb_allowSortPopup == false ) {
  825.                 this.yb_allowSortPopup = true;
  826.                 this.menupopup.showPopup(self, -1, -1, "popup", "bottomleft", "topleft");
  827.                 this.yb_allowSortPopup = false;
  828.                 }
  829.             };
  830.             
  831.             this.tagsSortMenu.yb_allowSortPopup = false;
  832.             this.tagsSortMenu.addEventListener("popupshowing", popupOnPopupShowing, true);
  833.             this.tagsSortMenu.addEventListener("click", popupOnClick, true);
  834.           
  835.             this.bookmarksSortMenu.yb_allowSortPopup = false;
  836.             this.bookmarksSortMenu.addEventListener("popupshowing", popupOnPopupShowing, true);
  837.             this.bookmarksSortMenu.addEventListener("click", popupOnClick, true);  
  838.           } 
  839.          
  840.          
  841.          
  842.          
  843.          
  844.          
  845.          
  846.           
  847.          // show the URL over when mousing over login links
  848.          this._loginMouseOverListener = {
  849.            handleEvent: function(event) {
  850.              var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  851.                      getService(Components.interfaces.nsIWindowMediator);
  852.              var recentWindow = wm.getMostRecentWindow("navigator:browser");
  853.              var url = event.target.getAttribute("url");
  854.              recentWindow.XULBrowserWindow.setOverLink(url);
  855.            }
  856.          };
  857.          
  858.          this._loginMouseOutListener = {
  859.             handleEvent: function(event) {
  860.               var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  861.                       getService(Components.interfaces.nsIWindowMediator);
  862.               var recentWindow = wm.getMostRecentWindow("navigator:browser");
  863.           
  864.               recentWindow.XULBrowserWindow.setOverLink("");
  865.             }
  866.           };    
  867.           
  868.           var ss = Components.classes["@yahoo.com/socialstore/delicious;1"].
  869.                                      getService(Components.interfaces.nsISocialStore);
  870.           var loginName = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-status");
  871.           loginName.addEventListener("mouseover", this._loginMouseOverListener, false);
  872.           loginName.addEventListener("mouseout", this._loginMouseOutListener, false);
  873.          
  874.           var loginDel = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-status-3");
  875.           loginDel.setAttribute("url", deliciousService.getUrl());
  876.           loginDel.addEventListener("mouseover", this._loginMouseOverListener, false);
  877.           loginDel.addEventListener("mouseout", this._loginMouseOutListener, false);
  878.   
  879.           var loginImage = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-image");
  880.           loginImage.setAttribute("url", deliciousService.getUrl());
  881.           loginImage.addEventListener("mouseover", this._loginMouseOverListener, false);
  882.           loginImage.addEventListener("mouseout", this._loginMouseOutListener, false);
  883.           
  884.           //Handles UI behaviour of querybox
  885.           //Makes use of css ybsidebar-search2 with the attribute status taking 2 values. 'focus' and 'inactive'.          
  886.           this.blurQueryBox = {
  887.               handleEvent: function(event) {                                                     
  888.                  var b = event.target;
  889.                  if(b) {                    
  890.                     b.setAttribute('status', 'inactive');                       
  891.                  }
  892.               }
  893.            };
  894.            this.activateQueryBox = {
  895.               handleEvent: function(event) {                                                     
  896.                 var b = event.target;
  897.                 if(b) {                 
  898.                     b.setAttribute('status', 'focus');                      
  899.                 }
  900.               }
  901.            };
  902.            var queryBox = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-search-query");
  903.            queryBox.setAttribute("status", "focus");
  904.            queryBox.addEventListener("blur", this.blurQueryBox, true);           
  905.            queryBox.addEventListener("focus", this.activateQueryBox, true);
  906.            
  907.            //Pinned or Unpinned Sidebar?, this call sets it
  908.            this.initPinState(); 
  909.            
  910.            //listen to select event of tagstree
  911.            this.tagsTree.addEventListener("select", this.resetSearchIcon, false);
  912.       ]]>  
  913.       </constructor>
  914.  
  915.       <destructor><![CDATA[
  916.         for (var i = 0; i < this.observedSubjects.length; i++) {
  917.            this.removeObserver(this.observedSubjects[i]);
  918.         }
  919.         bookmarksDataSource.RemoveObserver(this);
  920.         try {
  921.           var loginName = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-status");
  922.           loginName.removeEventListener("mouseover", this._loginMouseOverListener, false);
  923.           loginName.removeEventListener("mouseout", this._loginMouseOutListener, false);
  924.         } catch (e) {}
  925.         try {
  926.           var loginDel = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-status-3");
  927.           loginDel.removeEventListener("mouseover", this._loginMouseOverListener, false);
  928.           loginDel.removeEventListener("mouseout", this._loginMouseOutListener, false);
  929.         } catch(e) {}
  930.         try {
  931.           var loginImage = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-status-image");
  932.           loginImage.removeEventListener("mouseover", this._loginMouseOverListener, false);
  933.           loginImage.removeEventListener("mouseout", this._loginMouseOutListener, false);
  934.         } catch(e) {}
  935.         try {
  936.           var queryBox = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-search-query");
  937.           queryBox.removeEventListener("blur", this.blurQueryBox, true);           
  938.           queryBox.removeEventListener("focus", this.activateQueryBox, true);
  939.         } catch(e) {}        
  940.         
  941.         if(!this._pinned) {
  942.             this.removePinListeners();            
  943.         }     
  944.         //hack to restore standard sidebar header
  945.         var s = ybookmarksUtils.getTopWindow().document.getElementById("sidebar-box");           
  946.         s.firstChild.hidden = false;                
  947.         
  948.         //remove listening to select event of tagstree
  949.         this.tagsTree.removeEventListener("select", this.resetSearchIcon, false);
  950.         
  951.       ]]></destructor>
  952.       
  953.       
  954.       <field name="nextSyncTime">0</field>
  955.       <field name="DEFAULT_BOOKMARKS_THRESHOLD">2000</field>
  956.       <field name="SIDEBAR_SYNC_INTERVAL">2000</field>
  957.  
  958.       <field name="bookmarksStore">ybookmarksUtils.bookmarksStore</field>
  959.       <field name="_socialStore">ybookmarksUtils.socialStore</field>
  960.       <field name="_prefs">ybookmarksUtils.prefs</field>
  961.       <field name="bookmarksDataSource">this.bookmarksStore.getDataSource();</field>
  962.       <field name="searchDataSource">this.bookmarksStore.getSearchDataSource();</field>
  963.  
  964.       <field name="yTreeTagOriginalRef">"NC:YBookmarksTagRoot"</field>
  965.       <field name="yTreeBmOriginalRef">"NC:BookmarksRoot"</field>
  966.  
  967.       <field name="tagsTree">null</field>
  968.       <field name="bookmarksTree">null</field>
  969.  
  970.       <field name="_stringBundle">document.getAnonymousElementByAttribute(this, 
  971.           "anonid", "ybsidebar-stringbundle");</field>
  972.  
  973.       <field name="_showSidebarButton">document.getAnonymousElementByAttribute(this, 
  974.          "anonid", "ybsidebar-showSidebar");</field>
  975.       
  976.       <field name="_searchBox">document.getAnonymousElementByAttribute(this, 
  977.          "anonid", "ybsidebar-search-query");</field>
  978.       <field name="_splitter">document.getAnonymousElementByAttribute(this, 
  979.          "anonid", "ybsidebar-tree-splitter");</field>
  980.       <field name="_tagsLabelContainer">document.getAnonymousElementByAttribute(this, 
  981.          "anonid", "ybsidebar-tagsLabelContainer");</field>
  982.       <field name="_bookmarksLabelContainer">document.getAnonymousElementByAttribute(this, 
  983.          "anonid", "ybsidebar-bookmarksLabelContainer");</field>
  984.            
  985.       <field name="_noTagsResultsBox">document.getAnonymousElementByAttribute(this, 
  986.          "anonid", "ybbookmarks-no-tags-results");</field>
  987.       <field name="_noBookmarksResultsBox">document.getAnonymousElementByAttribute(this, 
  988.           "anonid", "ybbookmarks-no-bookmarks-results");</field>
  989.       <field name="_searchProgressMeter">document.getAnonymousElementByAttribute(this, "anonid", 
  990.                                                         "ybsidebar-search-progress-meter" );</field>
  991.       
  992.       <field name="tagsLabelContainerHeight">0</field>
  993.  
  994.       <!-- fields required for search progress bar functionality -->
  995.       <!-- How many bookmarks are searched till now. Reset this value for every search -->
  996.       <field name="_sofarSearched">0</field>
  997.       <!-- Is tag search still running? -->
  998.       <field name="_gotTagSearchEnd">false</field>
  999.       <!-- Is bookmarks search still running? -->
  1000.       <field name="_gotBookmarkSearchEnd">false</field>
  1001.  
  1002.       <field name="dirtyTags">new Object();</field>
  1003.       <field name="dirtyBookmarks">new Object();</field>
  1004.       
  1005.       <field name="_popupShowing">true</field>
  1006.       
  1007.       
  1008.       <field name="_pinned">true</field>
  1009.       <field name="_timeout">0</field>
  1010.       <field name="_canCloseSideBar">false</field>
  1011.       
  1012.       <field name="tagIsSelected">false</field>
  1013.  
  1014.       <method name="getElementByAnonid">
  1015.         <parameter name="anonid" />
  1016.         <body><![CDATA[
  1017.             return document.getAnonymousElementByAttribute(this, "anonid", anonid); 
  1018.         ]]></body>
  1019.       </method>
  1020.  
  1021.       
  1022.       <!-- Following functions are for the pinned feature -->
  1023.             
  1024.       <method name="addPinListeners">
  1025.         <body><![CDATA[
  1026.             this.addEventListener("blur", this.sidebarBlur, true);
  1027.             this.addEventListener("focus", this.sidebarFocus, true);            
  1028.             window.top.document.addEventListener("click", this.mouseListener, true);                    
  1029.             
  1030.             var info = Components.classes["@mozilla.org/xre/app-info;1"]
  1031.                      .getService(Components.interfaces.nsIXULAppInfo);
  1032.             var ver = info.version.substring(0,2);
  1033.             //Listening for tabselect event, this covers tabclose,tabopen and tabswitch.
  1034.             if(ver == "2.") {
  1035.                 //Works for FF2+
  1036.                 var container = window.top.document.getElementById("content").tabContainer;
  1037.                 if(container) {
  1038.                   container.addEventListener("TabSelect", this.timedClose, false);                   
  1039.                 }
  1040.             } else if(ver == "1.") {
  1041.                 var container = window.top.document.getElementById("content").mPanelContainer;
  1042.                 if(container) {
  1043.                     container.addEventListener("select", this.timedClose, false);
  1044.                 }
  1045.                 
  1046.             }
  1047.             //set sidebar pin button attributes
  1048.             var pinButton = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-pin-button");
  1049.             pinButton.setAttribute("class", "yb-nopin-button");
  1050.             pinButton.setAttribute("tooltiptext", this._stringBundle.getString("extensions.ybookmarks.ybsidebar.header.pinButttonOpenLabel", "Click to keep this sidebar open"));                                        
  1051.         ]]></body>
  1052.       </method>
  1053.       
  1054.       <method name="removePinListeners">
  1055.         <body><![CDATA[
  1056.             try {
  1057.                 this.removeEventListener("blur", this.sidebarBlur, true);                
  1058.             } catch(e) {}
  1059.             try {                
  1060.                 this.removeEventListener("focus", this.sidebarFocus, true);
  1061.             } catch(e) {}
  1062.             try {                
  1063.             window.top.document.removeEventListener("click", this.mouseListener, true);
  1064.             } catch(e) {}
  1065.             var info = Components.classes["@mozilla.org/xre/app-info;1"]
  1066.                      .getService(Components.interfaces.nsIXULAppInfo);
  1067.             var ver = info.version.substring(0,2);
  1068.             if(ver == "2.") {
  1069.                 //Works for FF2+
  1070.                 var container = window.top.document.getElementById("content").tabContainer;                
  1071.                 if(container) {
  1072.                     try {
  1073.                         container.removeEventListener("TabSelect", this.timedClose, false);                  
  1074.                     } catch(e) {}
  1075.                 }
  1076.             } else if(ver == "1.") {
  1077.                 var container = window.top.document.getElementById("content").mPanelContainer;
  1078.                 if(container) {
  1079.                     try {
  1080.                         container.removeEventListener("select", this.timedClose, false);
  1081.                     } catch(e) {}
  1082.                 }
  1083.             }
  1084.             var pinButton = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-pin-button");
  1085.             pinButton.setAttribute("class", "yb-pin-button");
  1086.             pinButton.setAttribute("tooltiptext", this._stringBundle.getString("extensions.ybookmarks.ybsidebar.header.pinButttonHideLabel", "Click to automatically hide this sidebar"));             
  1087.         ]]></body>
  1088.       </method>
  1089.       
  1090.       <method name="tryClosingSidebar">              
  1091.               <body><![CDATA[                
  1092.                 if(this._canCloseSideBar) {
  1093.                     this._canCloseSideBar = false;
  1094.                     window.clearTimeout(this._timeout);
  1095.                     window.top.ybsidebar.closeSidebar();
  1096.                 }                
  1097.                 
  1098.               ]]></body>
  1099.               </method>   
  1100.               
  1101.        <method name="sidebarBlur">
  1102.               <body><![CDATA[
  1103.                 this._canCloseSideBar = true;
  1104.                 var me = this;
  1105.                 _timeout = setTimeout(function() { me.tryClosingSidebar(); }, 500);
  1106.               ]]></body>
  1107.             </method>
  1108.  
  1109.        <method name="timedClose">
  1110.               <body><![CDATA[
  1111.                 setTimeout(window.top.ybsidebar.closeSidebar(),500);                
  1112.               ]]></body>
  1113.             </method>   
  1114.             
  1115.        <method name="sidebarFocus">
  1116.               <body><![CDATA[                
  1117.                 window.clearTimeout(this._timeout);
  1118.                 this._canCloseSideBar = false;
  1119.               ]]></body>
  1120.             </method>        
  1121.       
  1122.       <method name="mouseListener">
  1123.         <parameter name="event" />
  1124.         <body><![CDATA[                            
  1125.                var sidebar = window.top.document.getElementById("sidebar");
  1126.                if(sidebar) {
  1127.                  if(sidebar.boxObject) {   
  1128.                    if((event.screenX >= sidebar.boxObject.screenX) && (event.screenX <= (sidebar.boxObject.screenX + sidebar.boxObject.width + 10))
  1129.                       && (event.screenY >= sidebar.boxObject.screenY) && (event.screenY <= (sidebar.boxObject.screenY + sidebar.boxObject.height))) {
  1130.                         return true;  
  1131.                    } else {
  1132.                        if(!window.top.ybsidebar._pinned) {
  1133.                         setTimeout(window.top.ybsidebar.closeSidebar(),500);
  1134.                        }                  
  1135.                    }                                
  1136.                  }
  1137.                }
  1138.         ]]></body>
  1139.       </method>
  1140.       
  1141.       <method name="mouseListener">
  1142.         <parameter name="event" />
  1143.         <body><![CDATA[                            
  1144.                var sidebar = window.top.document.getElementById("sidebar");
  1145.                if(sidebar) {
  1146.                  if(sidebar.boxObject) {   
  1147.                    if((event.screenX >= sidebar.boxObject.screenX) && (event.screenX <= (sidebar.boxObject.screenX + sidebar.boxObject.width + 10))
  1148.                       && (event.screenY >= sidebar.boxObject.screenY) && (event.screenY <= (sidebar.boxObject.screenY + sidebar.boxObject.height))) {
  1149.                         return true;  
  1150.                    } else {
  1151.                        if(!window.top.ybsidebar._pinned) {
  1152.                         setTimeout(window.top.ybsidebar.closeSidebar(),500);
  1153.                        }                  
  1154.                    }                                
  1155.                  }
  1156.                }
  1157.         ]]></body>
  1158.       </method>
  1159.       
  1160.       <method name="initPinState">              
  1161.               <body><![CDATA[
  1162.                   try {
  1163.                     this._pinned = this._prefs.getBoolPref( "extensions.ybookmarks@yahoo.sidebar.pinned" );                    
  1164.                   } catch ( e ) {}                                    
  1165.                   if(!this._pinned) {
  1166.                     //Add listeners for pin
  1167.                     this.addPinListeners();
  1168.                   }
  1169.               ]]></body>
  1170.             </method>      
  1171.             
  1172.       <method name="togglePinState">              
  1173.               <body><![CDATA[
  1174.                   //toggle pin state
  1175.                   if(this._pinned == true) {
  1176.                     this._pinned = false;
  1177.                   } else {
  1178.                     this._pinned = true;
  1179.                   }
  1180.                   this._prefs.setBoolPref("extensions.ybookmarks@yahoo.sidebar.pinned", this._pinned);
  1181.                   var pinButton = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-pin-button");                  
  1182.                   if(!this._pinned) {
  1183.                     //Add listeners for pin
  1184.                     this.addPinListeners();                    
  1185.                   } else {
  1186.                     this.removePinListeners();                    
  1187.                   }
  1188.                   this.setSearchBoxFocus();
  1189.               ]]></body>
  1190.             </method>            
  1191.  
  1192.     <!--  end of pin functions -->
  1193.     
  1194.       <method name="periodicUpdate">
  1195.         <body><![CDATA[
  1196.         
  1197.             /*
  1198.              *  Process dirty tags
  1199.              */
  1200.             var dirtyTags       = this.dirtyTags;
  1201.             var tagsTreeView    = this.tagsTreeView;
  1202.             var needSort = false;
  1203.             tagsTreeView.treebox.beginUpdateBatch();
  1204.             for (var tag in dirtyTags) {
  1205.                 if (dirtyTags.hasOwnProperty(tag)) {
  1206.                     tagsTreeView.updateTag(tag, dirtyTags[tag]);
  1207.                     needSort = true;
  1208.                 }
  1209.             }
  1210.             yDebug.print("periodicUpdate: calling tagsTreeView.sortTable...");
  1211.             if (needSort) {
  1212.                 tagsTreeView.mergeTable();
  1213.             }
  1214.             tagsTreeView.treebox.endUpdateBatch();
  1215.             tagsTreeView.updateCount();
  1216.             this.dirtyTags = {};
  1217.             /*
  1218.              *  Process dirty bookmarks
  1219.              */
  1220.             var dirtyBookmarks       = this.dirtyBookmarks;
  1221.             needSort = false;
  1222.             var bookmarksTreeView    = this.bookmarksTreeView;
  1223.             bookmarksTreeView.treebox.beginUpdateBatch();
  1224.             for (var bookmark in dirtyBookmarks) {
  1225.                 if (dirtyBookmarks.hasOwnProperty(bookmark)) {
  1226.                     bookmarksTreeView.updateBookmark(bookmark, dirtyBookmarks[bookmark]);
  1227.                     needSort = true;
  1228.                 }
  1229.             }
  1230.             yDebug.print("periodicUpdate: calling bookmarksTreeView.sortTable...");
  1231.             if (needSort) {
  1232.                 bookmarksTreeView.mergeTable();
  1233.             }
  1234.             bookmarksTreeView.treebox.endUpdateBatch();
  1235.             bookmarksTreeView.updateCount();
  1236.             this.dirtyBookmarks = {};
  1237.             yDebug.print("periodicUpdate: done");
  1238.         ]]></body>
  1239.       </method>
  1240.  
  1241.       <method name="schedulePeriodicUpdate">
  1242.         <body><![CDATA[
  1243.             /**
  1244.              **  Schedule a periodic sync at next multiple of
  1245.              **  SIDEBAR_SYNC_INTERVAL if one isn't already
  1246.              **  scheduled
  1247.              **/
  1248.             var currTime = new Date().getTime();
  1249.             var nextSyncTime = Math.ceil(currTime / this.SIDEBAR_SYNC_INTERVAL) * this.SIDEBAR_SYNC_INTERVAL;
  1250.             if (nextSyncTime > this.nextSyncTime) {
  1251.                 var me = this;
  1252.                 setTimeout(function() { me.periodicUpdate(); }, currTime - nextSyncTime);
  1253.                 this.nextSyncTime = nextSyncTime;
  1254.             } 
  1255.         ]]></body>
  1256.       </method>
  1257.  
  1258.       <method name="processAssertOrUnassert">
  1259.         <parameter name="operation" />
  1260.         <parameter name="aDataSource" />
  1261.         <parameter name="aSubject" />
  1262.         <parameter name="aPredicate" />
  1263.         <parameter name="aTarget" />
  1264.         <body><![CDATA[
  1265.             var isDirty = false;
  1266.             var url = null;           
  1267.             if (this.removingAllData) return;        
  1268.             if (aDataSource == this.bookmarksDataSource) {           
  1269.                 if (aPredicate.EqualsNode(this.grscTag)) {
  1270.                     var tagName = aTarget.QueryInterface(this.nsIRDFLiteral).Value;
  1271.                     this.dirtyTags[tagName.toLowerCase()] = operation;
  1272.                     isDirty = true;
  1273.                 } else if (aPredicate.EqualsNode(this.grscUrl) && "unassert" === operation) {
  1274.                     url = aTarget.QueryInterface(this.nsIRDFLiteral).Value;
  1275.                     if (url) {
  1276.                         this.bookmarksTreeView.deleteBookmark(url);
  1277.                         isDirty = true;
  1278.                     }
  1279.                 }  
  1280.                 
  1281.                 url = this.bookmarkResource.getUrl(aSubject);
  1282.                 if (url) {
  1283.                     this.dirtyBookmarks[aSubject.Value] = url;
  1284.                     isDirty = true;
  1285.                 }
  1286.                 if (isDirty) {
  1287.                     this.schedulePeriodicUpdate();
  1288.                 }
  1289.             }
  1290.         ]]></body>
  1291.       </method>
  1292.  
  1293.       <method name="onAssert">
  1294.         <parameter name="aDataSource" />
  1295.         <parameter name="aSubject" />
  1296.         <parameter name="aPredicate" />
  1297.         <parameter name="aTarget" />
  1298.         <body><![CDATA[
  1299.                 this.processAssertOrUnassert("assert", aDataSource, aSubject, aPredicate, aTarget);
  1300.         ]]></body>
  1301.       </method>
  1302.  
  1303.       <method name="onUnassert">
  1304.         <parameter name="aDataSource" />
  1305.         <parameter name="aSubject" />
  1306.         <parameter name="aPredicate" />
  1307.         <parameter name="aTarget" />
  1308.         <body><![CDATA[
  1309.                 this.processAssertOrUnassert("unassert", aDataSource, aSubject, aPredicate, aTarget);
  1310.         ]]></body>
  1311.       </method>
  1312.  
  1313.       <method name="onChange">
  1314.         <parameter name="aDataSource" />
  1315.         <parameter name="aSubject" />
  1316.         <parameter name="aPredicate" />
  1317.         <parameter name="aOldTarget" />
  1318.         <parameter name="aNewTarget" />
  1319.         <body><![CDATA[
  1320.                 this.processAssertOrUnassert("change", aDataSource, aSubject, aPredicate, aNewTarget);
  1321.         ]]></body>
  1322.       </method>
  1323.  
  1324.       <method name="onBeginUpdateBatch">
  1325.         <parameter name="aDataSource" />
  1326.         <body><![CDATA[
  1327.             return true;
  1328.         ]]></body>
  1329.       </method>
  1330.  
  1331.       <method name="onEndUpdateBatch">
  1332.         <parameter name="aDataSource" />
  1333.         <body><![CDATA[
  1334.             return true;
  1335.         ]]></body>
  1336.       </method>
  1337.  
  1338.       <method name="observe">
  1339.         <parameter name="aSubject"/>
  1340.         <parameter name="aTopic"/>
  1341.         <parameter name="aData"/>
  1342.         <body>
  1343.                     <![CDATA[
  1344.  
  1345.           if (aTopic == "ybookmark.userChanged") {
  1346.  
  1347.             this._setLoginState();
  1348.  
  1349.           } else if ( aTopic == "ybookmarkSearch.begin" ) {
  1350.  
  1351.             // show the only when bookmarks search started. We do start bookmark search before
  1352.             // tags search.
  1353.             if ( aData == "tags" )
  1354.               return;
  1355.  
  1356.             this._showOrHideProgressmeter();
  1357.  
  1358.             // reset all the flags
  1359.             this._sofarSearched = 0;
  1360.             this._gotBookmarkSearchEnd = false;
  1361.             this._gotTagSearchEnd = false;
  1362.  
  1363.           } else if ( aTopic == "ybookmarkSearch.end" ) {
  1364.  
  1365.             // wait for both tags and bookmarks search to finish before hiding the 
  1366.             // the progressbar.
  1367.             if ( !this._gotTagSearchEnd )
  1368.               this._gotTagSearchEnd = (aSubject.wrappedJSObject.type == "tags");
  1369.             if ( !this._gotBookmarkSearchEnd )
  1370.               this._gotBookmarkSearchEnd = (aSubject.wrappedJSObject.type == "bookmarks");
  1371.  
  1372.             if ( this._gotBookmarkSearchEnd && this._gotTagSearchEnd ) {
  1373.               this._searchProgressMeter.value = 100;
  1374.               var meter = this._searchProgressMeter;
  1375.               // do not hide the progressbar immedietly. Wait for 900 milli seconds. 
  1376.               // Should this be configurable?
  1377.               setTimeout( function() {
  1378.                                           meter.collapsed = true;
  1379.                                           meter.hidden = true;
  1380.                                      },
  1381.                           900 
  1382.                         );
  1383.             }
  1384.  
  1385.             // If no results from tags search, show the no results pane. Otherwise hide the
  1386.             // the no results pane.
  1387.             if ( aSubject.wrappedJSObject.type == "tags" ) {
  1388.               if ( aSubject.wrappedJSObject.totalMatched == 0 ) {
  1389.                 this._showNoSearchResults("tags", true);
  1390.               } else {
  1391.                 this._showNoSearchResults("tags", false);
  1392.               }
  1393.             }
  1394.  
  1395.             // If no results from bookmarks search, show the no results pane. Otherwise hide the
  1396.             // the no results pane.
  1397.             if ( aSubject.wrappedJSObject.type == "bookmarks" ) {
  1398.               if ( aSubject.wrappedJSObject.totalMatched == 0 ) {
  1399.                 this._showNoSearchResults("bookmarks", true);
  1400.               } else {
  1401.                 this._showNoSearchResults("bookmarks", false);
  1402.               }
  1403.             }
  1404.  
  1405.             yDebug.print("************ b4 _populateTreesWithSearchResults: this._searchBox.value =\"" + this._searchBox.value + "\"");
  1406.             this._populateTreesWithSearchResults(aSubject.wrappedJSObject.type, this._searchBox.value);
  1407.  
  1408.           } else if ( aTopic == "ybookmarkSearch.inProgress" ) {
  1409.  
  1410.             // Calculate the percentage of search done.
  1411.             this._sofarSearched += aSubject.wrappedJSObject.sofar;
  1412.             this._searchProgressMeter.value = ( 100 * this._sofarSearched ) / aSubject.wrappedJSObject.total;
  1413.           
  1414.           } else if ( aTopic == "ybookmark.importBookmarks" ) {
  1415.             
  1416.             if (this._searchBox.value) {
  1417.               return;
  1418.             }            
  1419.  
  1420.  
  1421.             aSubject.QueryInterface(Components.interfaces.nsISupportsString);
  1422.             if ((aSubject.data == "importProgress" && (aData == "complete" || aData == "failed")) 
  1423.                    || aSubject.data == "importError") {
  1424.  
  1425.               var tagsRef = this._getTreeRef("tags");
  1426.               this.tagsTree.setAttribute("ref", tagsRef);
  1427.               var bookmarksRef = this._getTreeRef("bookmarks")
  1428.               this.bookmarksTree.setAttribute("ref", bookmarksRef);
  1429.                 
  1430.               if (tagsRef.length) {
  1431.                 this._showNoSearchResults("tags", false);
  1432.                 this._showNoSearchResults("bookmarks", false);
  1433.               }
  1434.               else {
  1435.                 this._showEmptyPane("tags");
  1436.                 this._showEmptyPane("bookmarks");
  1437.               }
  1438.             }
  1439.             else {              
  1440.               
  1441.               if (!this._hasBookmarks()) {
  1442.                 this._showImportingPane("tags");
  1443.                 this._showImportingPane("bookmarks");
  1444.               }
  1445.               else {
  1446.                 var tagsRef = this._getTreeRef("tags");
  1447.                 this.tagsTree.setAttribute("ref", tagsRef);
  1448.                 var bookmarksRef = this._getTreeRef("bookmarks")
  1449.                 this.bookmarksTree.setAttribute("ref", bookmarksRef);
  1450.                 
  1451.                 if (tagsRef.length) {
  1452.                   this._showNoSearchResults("tags", false);
  1453.                   this._showNoSearchResults("bookmarks", false);
  1454.                 }
  1455.                 else {
  1456.                   this._showEmptyPane("tags");
  1457.                   this._showEmptyPane("bookmarks");
  1458.                 }
  1459.               }
  1460.             }
  1461.           } else if ("ybookmark.syncBegin" === aTopic) {
  1462.               if ("remove-extra" === aData) {
  1463.                   this.removingAllData = true;
  1464.               }
  1465.           } else if ("ybookmark.syncDone" === aTopic) {
  1466.               if ("remove-extra" === aData) {
  1467.                   this.removingAllData = false;
  1468.                   yDebug.print("*** Received \"remove-extra\" message; reloading both tree views");
  1469.                   this.tagsTreeView.loadTable();
  1470.                   this.bookmarksTreeView.loadTable();
  1471.               } else {
  1472.                   this.schedulePeriodicUpdate();
  1473.               }
  1474.               if ("all-done" === aData) {                
  1475.                 this.tagsTreeView.sortTable(); 
  1476.               }
  1477.           } else if ("ybookmark.bookmarkDeleted" === aTopic) {
  1478.               this.bookmarksTreeView.treebox.invalidate();
  1479.             this.bookmarksTreeView.loadTable();
  1480.             this.bookmarksTreeView.sortTable();
  1481.           }
  1482.         ]]></body>
  1483.       </method>
  1484.  
  1485.       <method name="_populateTreesWithSearchResults">
  1486.         <parameter name="type"/>     
  1487.         <parameter name="searchTerm"/>     
  1488.         <body><![CDATA[
  1489.             yDebug.print("ybSidebarOverlay._populateTreesWithSearchResults: type = " + type + "; searchTerm = " + searchTerm);
  1490.             var storeNumber;
  1491.             if (this.parentNode.nodeName == "popup") {        
  1492.                 storeNumber = 2;
  1493.             }
  1494.             else {
  1495.                 storeNumber = 1;
  1496.             }
  1497.             if (type == "tags") {
  1498.                 this.tagsTreeView.setData(new this.tagsTreeDataSearch(storeNumber, searchTerm));
  1499.                 this.tagsTreeView.sortTable();
  1500.             } else if (type == "bookmarks") {
  1501.                 this.bookmarksTreeView.setData(new this.bookmarksTreeDataSearch(storeNumber, searchTerm));
  1502.                 this.bookmarksTreeView.sortTable();
  1503.             }
  1504.             
  1505.         ]]></body>
  1506.       </method>
  1507.       
  1508.       <method name="_hasBookmarks">
  1509.         <body><![CDATA[
  1510.           
  1511.               var datasource = this.bookmarksStore.getDataSource();
  1512.               var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].
  1513.                                    getService(Components.interfaces.nsIRDFService);
  1514.               var rdfContainerUtils = Components.classes["@mozilla.org/rdf/container-utils;1"].
  1515.                                          getService(Components.interfaces.nsIRDFContainerUtils);
  1516.               var bookmarksRoot = rdfContainerUtils.MakeSeq(datasource, rdfService.GetResource ( "NC:BookmarksRoot" ));
  1517.               var allBookmarkResources = bookmarksRoot.GetElements();
  1518.               var counter = 0;
  1519.               while (allBookmarkResources.hasMoreElements()) {
  1520.                 bookmarkResource = allBookmarkResources.getNext();
  1521.                 counter ++;
  1522.                 if (counter > 1){
  1523.                   return true;
  1524.                 }  
  1525.               }
  1526.           
  1527.            return false;
  1528.            
  1529.         ]]></body>
  1530.       </method>
  1531.  
  1532.       
  1533.       <method name="_setLoginState">
  1534.         <body><![CDATA[
  1535.           
  1536.           var username = this._socialStore.getUserName();
  1537.           var element = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-login-status");
  1538.           try{
  1539.             element.removeEventListener("click", this._login, true);
  1540.           }
  1541.           catch(e) {}
  1542.  
  1543.           if (username) {
  1544.             var url = deliciousService.getUrl(username);
  1545.  
  1546.             element.removeAttribute("class");
  1547.             element.setAttribute("value", username);
  1548.             element.setAttribute("onclick", "_openUrl(event, '" + url + "')");
  1549.             element.setAttribute("class", "ysidebar-textlink");
  1550.             element.setAttribute("linktype", "standard");
  1551.             element.setAttribute("url", url);
  1552.           }
  1553.           else {
  1554.             var ss = Components.classes["@yahoo.com/socialstore/delicious;1"].
  1555.                                        getService(Components.interfaces.nsISocialStore);
  1556.  
  1557.             element.addEventListener("click", this._login, true);
  1558.             element.setAttribute("class", "ysidebar-textlink");
  1559.             element.setAttribute("value", this._stringBundle.getString("ybookmarks.login", [username]));
  1560.             element.setAttribute("url", ss.login_url);
  1561.              
  1562.           }
  1563.           
  1564.         ]]></body>     
  1565.       </method>
  1566.       
  1567.       <method name="search">
  1568.       <parameter name="input"/>     
  1569.       <body><![CDATA[           
  1570.            this._searchBox.value = input;
  1571.            this._search(input);     
  1572.            this.setSearchBoxFocus();           
  1573.         ]]></body>
  1574.        </method>
  1575.  
  1576.       <method name="setSearchBoxFocus">
  1577.       <body><![CDATA[           
  1578.            //hack to hide standard sidebar header
  1579.            var s = ybookmarksUtils.getTopWindow().document.getElementById("sidebar-box");           
  1580.            s.firstChild.hidden = true;
  1581.            this._searchBox.focus();           
  1582.          ]]></body>
  1583.        </method>
  1584.  
  1585.       <method name="setSearchBoxSelect">
  1586.       <body><![CDATA[           
  1587.            if (this._searchBox.value.length) {
  1588.              this._searchBox.select();
  1589.            }
  1590.            this.setSearchBoxFocus();            
  1591.          ]]></body>
  1592.       </method>
  1593.  
  1594.  
  1595.       <method name="enableSidebarSwitch">
  1596.         <parameter name="bool"/>     
  1597.         <body><![CDATA[         
  1598.           
  1599.           if (!this._showSidebarButton)
  1600.             this._showSidebarButton = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-showSidebar");
  1601.  
  1602.           if (bool) {
  1603.             this._showSidebarButton.disabled = false;
  1604.           }
  1605.           else {
  1606.             this._showSidebarButton.disabled = true;
  1607.           }
  1608.                     
  1609.        ]]></body>
  1610.       </method>
  1611.  
  1612.       <method name="_openYBSidebar">
  1613.         <body><![CDATA[         
  1614.  
  1615.           if (this.parentNode.nodeName == "popup") {        
  1616.  
  1617.             toggleSidebar("viewYBookmarksSidebar", true);
  1618.                      
  1619.             setTimeout(function(keyword) {
  1620.               var sidebar = document.getElementById("sidebar"); 
  1621.               if (sidebar) { 
  1622.                 var ybsidebars = sidebar.contentDocument.firstChild.getElementsByTagName("ybsidebar");
  1623.                 if (ybsidebars.length) {
  1624.                   ybsidebars[0].search(keyword);
  1625.                 }               
  1626.               }
  1627.             }, 20, this._searchBox.value);
  1628.  
  1629.             this._shouldClosePopup(false);            
  1630.            
  1631.           }
  1632.                     
  1633.        ]]></body>
  1634.       </method> 
  1635.       
  1636.       
  1637.       
  1638.       <method name="_setLastSidebarSearchValue">
  1639.         <parameter name="keyword"/>
  1640.         <body><![CDATA[
  1641.           if (this.parentNode.nodeName != "popup") {        
  1642.             window.top.ybsidebar.lastSidebarSearchValue = keyword;
  1643.           }
  1644.           else {
  1645.             ybsidebar.lastSidebarSearchValue = keyword;
  1646.           }
  1647.        ]]></body>
  1648.       </method>
  1649.  
  1650.  
  1651.       <method name="_getLastSidebarSearchValue">
  1652.         <body><![CDATA[
  1653.           if (this.parentNode.nodeName != "popup") {        
  1654.             return window.top.ybsidebar.lastSidebarSearchValue;
  1655.           }
  1656.           else {
  1657.             return ybsidebar.lastSidebarSearchValue;
  1658.           }
  1659.  
  1660.        ]]></body>
  1661.       </method>
  1662.  
  1663.       <method name="setPopupSize">
  1664.         <body><![CDATA[
  1665.            if (this.parentNode.nodeName == "popup") {        
  1666.  
  1667.              //set height            
  1668.              //overlay.css .ybsidebar-tree-container
  1669.              var minTreesContainerHeight = 335;
  1670.              var windowHeight = document.documentElement.boxObject.height;
  1671.              var treesContainer = document.getAnonymousElementByAttribute(this, "class", "ybsidebar-tree-container");             
  1672.              
  1673.              var newTreesContainerHeight = parseInt(windowHeight) - 225;
  1674.              if (newTreesContainerHeight > minTreesContainerHeight) {
  1675.                treesContainer.setAttribute("minheight", newTreesContainerHeight);
  1676.                treesContainer.setAttribute("maxheight", newTreesContainerHeight);
  1677.              }
  1678.              else {
  1679.                treesContainer.setAttribute("minheight", minTreesContainerHeight);
  1680.                treesContainer.setAttribute("maxheight", minTreesContainerHeight);
  1681.              }
  1682.              
  1683.              var tagsTreeContainer = this.tagsTree.parentNode.parentNode;
  1684.              var tagsTreeContainerHeight = tagsTreeContainer.getAttribute("minheight");
  1685.              if (tagsTreeContainerHeight) {
  1686.              
  1687.                treesContainerHeight =  treesContainer.getAttribute("minheight");
  1688.                
  1689.                if (parseInt(tagsTreeContainerHeight) > parseInt(treesContainerHeight)) {
  1690.  
  1691.                  var newTreeHeight = treesContainerHeight - (22 + (this.tagsLabelContainerHeight * 2));
  1692.                  tagsTreeContainer.setAttribute("minheight", newTreeHeight);
  1693.                  tagsTreeContainer.setAttribute("maxheight", newTreeHeight);                 
  1694.                }
  1695.              }
  1696.              
  1697.              //set width
  1698.              this.setAttribute("minwidth", 250);
  1699.              this.setAttribute("maxwidth", 250);
  1700.              
  1701.            }
  1702.          ]]></body>
  1703.        </method>
  1704.  
  1705.       <method name="_createContextMenu">
  1706.         <parameter name="event"/>
  1707.         <body><![CDATA[
  1708.  
  1709.          var target = document.popupNode;
  1710.          var tree = this._getTree(target);
  1711.          if(!tree) {
  1712.            target.removeAttribute("open");
  1713.            return false;         
  1714.          }
  1715.          var row = tree.currentIndex;
  1716.          var col = tree.columns.getNamedColumn('Name');
  1717.          var url = tree.view.getCellValue(row, col);
  1718.  
  1719.          var livemark = this._isCurrentLivemark(tree);
  1720.                 
  1721.          if (!livemark && (tree.view.isContainer(row)  || !url) && (url != "_yb_tag_entity")) {
  1722.            target.removeAttribute("open");
  1723.            return false;
  1724.          }
  1725.          var menu = document.getAnonymousElementByAttribute( this, "id", "ybContextMenu" );
  1726.          var i;
  1727.          if (url == "_yb_tag_entity") {         // tag
  1728.            for( i = 0; i < menu.childNodes.length; ++i ) {
  1729.              ( menu.childNodes[ i ] ).hidden = true;
  1730.            }
  1731.           ( document.getAnonymousElementByAttribute(
  1732.                        this, "anonid", "ybContextMenu-openContainer" ) ).hidden = false;
  1733.           ( document.getAnonymousElementByAttribute(
  1734.                        this, "anonid", "ybContextMenu-openTag" ) ).hidden = false;
  1735.          }
  1736.          else if (livemark) {
  1737.            for( i = 0; i < menu.childNodes.length; ++i ) {
  1738.              ( menu.childNodes[ i ] ).hidden = true;
  1739.            }
  1740.            ( document.getAnonymousElementByAttribute(
  1741.                         this, "anonid", "ybContextMenu-delete-bookmark" ) ).hidden = false;
  1742.            ( document.getAnonymousElementByAttribute(
  1743.                         this, "anonid", "ybContextMenu-separator3" ) ).hidden = false;
  1744.            ( document.getAnonymousElementByAttribute( 
  1745.                         this, "anonid", "ybContextMenu-about" ) ).hidden = false;
  1746.            ( document.getAnonymousElementByAttribute( 
  1747.                         this, "anonid", "ybContextMenu-properties" ) ).hidden = false;
  1748.          } 
  1749.          else {                                // normal bookmark
  1750.            for( i = 0; i < menu.childNodes.length; ++i ) {
  1751.              ( menu.childNodes[ i ] ).hidden = false;
  1752.            }
  1753.            ( document.getAnonymousElementByAttribute( 
  1754.                         this, "anonid", "ybContextMenu-openContainer" ) ).hidden = true;
  1755.           ( document.getAnonymousElementByAttribute(
  1756.                         this, "anonid", "ybContextMenu-openTag" ) ).hidden = true;
  1757.          }                  
  1758.          return true;
  1759.         ]]></body>
  1760.       </method>
  1761.         
  1762.       <method name="_openURLIn">
  1763.         <parameter name="event"/>
  1764.         <parameter name="tree"/>
  1765.         <parameter name="where"/>
  1766.         <body><![CDATA[
  1767.             try {
  1768.                 var row = tree.currentIndex;
  1769.                 if (tree.view.rowCount <= 0) {
  1770.                     return;
  1771.                 }
  1772.  
  1773.                 if (!tree.view.isContainer(row)) {
  1774.                     var url = tree.view.getCellValue(row, tree.columns.getNamedColumn("Name"));
  1775.                     if (url != "_yb_tag_entity") {
  1776.                         event.target.setAttribute("type", "http://home.netscape.com/NC-rdf#Bookmark");
  1777.                         event.target.setAttribute("url", url);  
  1778.                         ybookmarksUtils.openBookmark(event, where);
  1779.                         //hack
  1780.                         if(!this._pinned) {
  1781.                             this._canCloseSideBar = true;
  1782.                             this.sidebarBlur();
  1783.                         }
  1784.                         this._shouldClosePopup(true);                        
  1785.                     }
  1786.                 }
  1787.             } catch (e) { yDebug.print(e, YB_LOG_MESSAGE); }
  1788.          ]]></body>
  1789.        </method>
  1790.  
  1791.       <method name="_newBookmark">
  1792.         <body><![CDATA[          
  1793.            if(this._pinned) {
  1794.                  ybBookmarksMenu.newBookmark();                 
  1795.            } else {
  1796.                //hack for unpinned mode alone           
  1797.                Components.classes["@mozilla.org/observer-service;1"]
  1798.                      .getService(Components.interfaces.nsIObserverService)
  1799.                    .notifyObservers(null, "ybookmark.addBookmark", "");
  1800.                window.top.ybsidebar.closeSidebar();    
  1801.            }
  1802.          ]]></body>
  1803.        </method>
  1804.       
  1805.       <method name="_editBookmark">
  1806.         <parameter name="event"/>
  1807.         <parameter name="tree"/>
  1808.         <body><![CDATA[          
  1809.            var row = tree.currentIndex;
  1810.            var url = tree.view.getCellValue(row, tree.columns.getNamedColumn('Name'));           
  1811.            if(this._pinned) {               
  1812.                yAddBookMark.open(url);           
  1813.            } else {
  1814.                //trick for unpinned mode alone
  1815.                Components.classes["@mozilla.org/observer-service;1"]
  1816.                      .getService(Components.interfaces.nsIObserverService)
  1817.                    .notifyObservers(null, "ybookmark.addBookmark", url);
  1818.                window.top.ybsidebar.closeSidebar();    
  1819.            }
  1820.          ]]></body>
  1821.        </method>
  1822.  
  1823.       <method name="_moreAbout">
  1824.         <parameter name="event"/>
  1825.         <parameter name="tree"/>
  1826.         <body><![CDATA[
  1827.                try {
  1828.                  var row = tree.currentIndex;
  1829.                  var url = tree.view.getCellValue(row, tree.columns.getNamedColumn('Name'));
  1830.                                  var livemark = this._isCurrentLivemark(tree);
  1831.                                 
  1832.                  if (livemark || !tree.view.isContainer(row)) {
  1833.                     event.target.setAttribute("type", "http://home.netscape.com/NC-rdf#Bookmark");
  1834.                     event.target.setAttribute("url",
  1835.                         deliciousService.getMoreAboutUrl(url));
  1836.                     ybookmarksUtils.openBookmark(event, "current");
  1837.                     
  1838.                     this._shouldClosePopup(true);
  1839.                  }
  1840.  
  1841.                } catch (e) { yDebug.print( "ybSidebarOverlay._moreAbout(): " + e, YB_LOG_MESSAGE); }
  1842.  
  1843.          ]]></body>
  1844.        </method>
  1845.  
  1846.       <method name="_openTag">
  1847.         <parameter name="event"/>
  1848.         <parameter name="tree"/>
  1849.         <body><![CDATA[
  1850.           try {
  1851.             var row = tree.currentIndex;
  1852.             var value = tree.view.getCellText( row, ( tree.columns ).getNamedColumn( 'Name' ) );
  1853.             ybookmarksUtils.openTag(value, event);
  1854.           } catch ( e ) { 
  1855.             yDebug.print( "ybSidebarOverlay._openTag() exception: " + e, YB_LOG_MESSAGE); 
  1856.           }
  1857.         ]]></body>
  1858.       </method>
  1859.  
  1860.  
  1861.       <!-- This method opens all children in the bookmark view. -->
  1862.       <method name="_openContainer">
  1863.         <parameter name="event"/>
  1864.         <parameter name="tree"/>
  1865.         <body><![CDATA[
  1866.           try {
  1867.             var row = tree.currentIndex;
  1868.             var value = tree.view.getCellValue( row, ( tree.columns ).getNamedColumn( 'Name' ) );
  1869.             if( value == "_yb_tag_entity" ) {
  1870.               if( tree.view.isContainerOpen( row ) ) {
  1871.                 var urls = new Array();
  1872.                 var i = row + 1;
  1873.                 while( i < tree.view.rowCount ) {
  1874.                   if( tree.view.getParentIndex( i ) != row ) {
  1875.                     break;
  1876.                   }
  1877.                   value = tree.view.getCellValue( i, ( tree.columns ).getNamedColumn( 'Name' ) );
  1878.                   urls.push( value );
  1879.                   ++i;
  1880.                 }
  1881.                 YBtabsOpener.openURLsInNewTab( urls );
  1882.               }
  1883.               else {
  1884.                 tree.view.toggleOpenState( row );
  1885.                 this._openContainer( event, tree );
  1886.               }
  1887.             }
  1888.           } 
  1889.           catch ( e ) { 
  1890.             yDebug.print( "ybSidebarOverlay._openContainer() exception: " + e, YB_LOG_MESSAGE); 
  1891.           }
  1892.         ]]></body>
  1893.       </method>
  1894.  
  1895.  
  1896.       <!-- This method opens all bookmarks currently visible in the bookmark view. -->
  1897.       <method name="_openBookmarks">
  1898.         <parameter name="event"/>
  1899.         <parameter name="tree"/>
  1900.         <body><![CDATA[
  1901.           try {
  1902.                 var urls = new Array();
  1903.                 for(i = 0; i < this.bookmarksTreeView.table.length; ++i) {
  1904.                     var bm = this.bookmarksTreeView.table[i];
  1905.                     if (!bm.isLivemark()) {
  1906.                         urls.push(bm.url);
  1907.                     }
  1908.                 }
  1909.                 YBtabsOpener.openURLsInNewTab( urls );
  1910.           } 
  1911.           catch ( e ) { 
  1912.             yDebug.print( "ybSidebarOverlay._openBookmarks() exception: " + e, YB_LOG_MESSAGE); 
  1913.           }
  1914.         ]]></body>
  1915.       </method>
  1916.  
  1917.       <method name="_openHome">
  1918.         <parameter name="event"/>
  1919.         <body><![CDATA[
  1920.         
  1921.            var element = event.target;
  1922.            while (element) {
  1923.              if (element.nodeName == "ybsidebar") { 
  1924.                break;
  1925.              }
  1926.              element = element.parentNode;
  1927.            }
  1928.            event.target.setAttribute("type", "http://home.netscape.com/NC-rdf#Bookmark");
  1929.            event.target.setAttribute("url", deliciousService.getUrl());   
  1930.            ybookmarksUtils.openBookmark(event, "current");
  1931.                     
  1932.            element._shouldClosePopup(true);
  1933.  
  1934.          ]]></body>
  1935.        </method>
  1936.  
  1937.       <method name="_openUrl">
  1938.         <parameter name="event"/>
  1939.         <parameter name="url"/>
  1940.         <body><![CDATA[
  1941.         
  1942.            var element = event.target;
  1943.            while (element) {
  1944.              if (element.nodeName == "ybsidebar") { 
  1945.                break;
  1946.              }
  1947.              element = element.parentNode;
  1948.            }
  1949.            event.target.setAttribute("type", "http://home.netscape.com/NC-rdf#Bookmark");
  1950.            event.target.setAttribute("url", url);   
  1951.            ybookmarksUtils.openBookmark(event, "current");
  1952.                     
  1953.            element._shouldClosePopup(true);
  1954.  
  1955.          ]]></body>
  1956.        </method>
  1957.  
  1958.       <method name="_login">
  1959.         <parameter name="event"/>
  1960.         <body><![CDATA[
  1961.         
  1962.            var element = event.target;
  1963.            while (element) {
  1964.              if (element.nodeName == "ybsidebar") { 
  1965.                break;
  1966.              }
  1967.              element = element.parentNode;
  1968.            }
  1969.            event.target.setAttribute("type", "http://home.netscape.com/NC-rdf#Bookmark");
  1970.            event.target.setAttribute("url", deliciousService.getLoginUrl());   
  1971.            ybookmarksUtils.openBookmark(event, "current");
  1972.                     
  1973.            element._shouldClosePopup(true);
  1974.  
  1975.          ]]></body>
  1976.        </method>
  1977.  
  1978.  
  1979.       <method name="_deleteBookmark">
  1980.         <parameter name="event"/>
  1981.         <parameter name="tree"/>
  1982.         <body><![CDATA[
  1983.         
  1984.           this._shouldClosePopup(false);
  1985.           
  1986.         /*  if( !YBidManager.isUserLoggedIn() ) {
  1987.             YBidManager.promptUserLogin();
  1988.             return;
  1989.           }*/
  1990.                     
  1991.           var row = tree.currentIndex;
  1992.           var url = tree.view.getCellValue(row, tree.columns.getNamedColumn('Name'));
  1993.           
  1994.           //We need to hack here to retain sidebar in unpinned mode
  1995.           var flipped = false;
  1996.           if(!this._pinned) {
  1997.               flipped = true;
  1998.           }
  1999.           if(flipped) {
  2000.               this.removePinListeners();
  2001.           }          
  2002.           //show UI
  2003.           ybBookmarksMenu.deleteBookmark(url);
  2004.  
  2005. //          tree.treeBoxObject.invalidate();
  2006.           /**
  2007.            * Hack was added to refresh treeboxobject which is not getting updated even after deleting a bookmark
  2008.            */         
  2009.           window.setTimeout(function () { tree.treeBoxObject.invalidate(); }, 600);
  2010.           
  2011.           
  2012.           if(flipped) {
  2013.               //Add all listeners for pin
  2014.               this.addPinListeners();
  2015.           }
  2016.           //end of hack
  2017.           
  2018.           /*this.bookmarksStore.deleteBookmark(url);
  2019.           var post = { url : url }; 
  2020.           post.wrappedJSObject = post;
  2021.  
  2022.           this.bookmarksStore.addTransaction("deleteBookmark", 0, post);          
  2023.           var syncService = Components.classes["@mozilla.org/ybookmarks-sync-service;1"].
  2024.               getService(Components.interfaces.nsIYBookmarkSyncService);                                 
  2025.           syncService.processTransactions();
  2026. */
  2027.          ]]></body>
  2028.        </method>
  2029.  
  2030.      <method name="_showOrHideProgressmeter">
  2031.         <body><![CDATA[
  2032.                 var threshold = this.DEFAULT_BOOKMARKS_THRESHOLD;
  2033.                 try {
  2034.                   threshold = this._prefs.getIntPref( "extensions.ybookmarks@yahoo.bookmark.threshold" );
  2035.                 } catch ( e ) { }
  2036.  
  2037.                 if ( this.bookmarksStore.getTotalBookmarks() > threshold ) {
  2038.  
  2039.                   var meter = this._searchProgressMeter;
  2040.                   meter.value = 0;
  2041.                   meter.collapsed = false;
  2042.                   meter.hidden = false;
  2043.                 } else {
  2044.                   var meter = this._searchProgressMeter;
  2045.                   meter.collapsed = true;
  2046.                   meter.hidden = true;
  2047.                 }
  2048.         ]]></body>
  2049.      </method>    
  2050.      
  2051.      
  2052.      <!-- Following 2 functions are for setting the right icons -->
  2053.      <method name="iconHandler">
  2054.         <parameter name="aInput"/>
  2055.            <body><![CDATA[
  2056.  
  2057.            if(aInput == "") { 
  2058.                 this.getElementByAnonid("ybsidebar-search-reset").image = "chrome://ybookmarks/skin/searchIcon.gif";
  2059.            } else {
  2060.                 this.getElementByAnonid("ybsidebar-search-reset").image = "chrome://ybookmarks/skin/searchReset.gif";
  2061.            }
  2062.            //this.getElementByAnonid("ybsidebar-search-query").setAttribute('status', 'focus');
  2063.            ]]></body>
  2064.      </method>     
  2065.      
  2066.      <method name="reseticonHandler">
  2067.           <parameter name="aInput"/>
  2068.            <body><![CDATA[
  2069.            var input = this.getElementByAnonid("ybsidebar-search-query").value;
  2070.            if(input == "" && !this.tagIsSelected) { 
  2071.                 this.getElementByAnonid("ybsidebar-search-reset").image = "chrome://ybookmarks/skin/searchIcon.gif";
  2072.            } else {
  2073.                 if(aInput == 'hover') {
  2074.                 this.getElementByAnonid("ybsidebar-search-reset").image = "chrome://ybookmarks/skin/searchReset.gif";
  2075.                 } else {
  2076.                 this.getElementByAnonid("ybsidebar-search-reset").image = "chrome://ybookmarks/skin/searchReset.gif";
  2077.                 }
  2078.            }
  2079.            ]]></body>
  2080.      </method>
  2081.  
  2082.      <method name="resetSearchIcon">
  2083.            <body><![CDATA[
  2084.            try {
  2085.                 var sidebar = this.parentNode.parentNode.parentNode.parentNode.parentNode;
  2086.                 sidebar.tagIsSelected = true;
  2087.                 document.getAnonymousElementByAttribute(sidebar, "anonid", "ybsidebar-search-reset").image = "chrome://ybookmarks/skin/searchReset.gif";
  2088.                 } catch(e) {} 
  2089.            ]]></body>
  2090.      </method>     
  2091.  
  2092.      <method name="_search">
  2093.         <parameter name="aInput"/>
  2094.            <body><![CDATA[
  2095.               var storeNumber;
  2096.               if (this.parentNode.nodeName == "popup") {        
  2097.                 storeNumber = 2;
  2098.               }
  2099.               else {
  2100.                 storeNumber = 1;
  2101.               }
  2102.               this._setLastSidebarSearchValue(aInput);
  2103.  
  2104.               if (!aInput) {
  2105.                 this.reset();
  2106.               }   
  2107.               else {
  2108.                 this._showOrHideProgressmeter();
  2109.  
  2110.                 this._showNoSearchResults("tags", false);
  2111.                 this._showNoSearchResults("bookmarks", false);
  2112.  
  2113.         this.bookmarksStore.searchBookmarks(aInput, storeNumber);
  2114.         this.bookmarksStore.searchTags(aInput, storeNumber);
  2115.               }                
  2116.             ]]></body>
  2117.      </method>
  2118.  
  2119.      <method name="reset">
  2120.        <body><![CDATA[
  2121.            this._searchBox.value ="";           
  2122.            this._setLastSidebarSearchValue("");
  2123.            this.tagsTreeView.setData(this.tagsTreeData);
  2124.            this.tagsTreeView.clearSelection();
  2125.            this.tagsTreeView.sortTable();
  2126.            this._showNoSearchResults("tags", false);
  2127.            this.bookmarksTreeView.setData(this.bookmarksTreeData);
  2128.            this.bookmarksTreeView.clearSelection();
  2129.            this.bookmarksTreeView.sortTable();
  2130.            this._showNoSearchResults("bookmarks", false);
  2131.            this.tagIsSelected = false;
  2132.        ]]></body>
  2133.      </method>
  2134.  
  2135.       <method name="_showNoSearchResults">
  2136.         <parameter name="type"/>     
  2137.         <parameter name="show"/>     
  2138.         <body><![CDATA[         
  2139.            
  2140.            var index = show? 1 : 0;
  2141.            if (type == "tags") {
  2142.              
  2143.              var deck = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-tags-deck");
  2144.              deck.setAttribute("selectedIndex", index);
  2145.              this._noTagsResultsBox.firstChild.setAttribute("selectedIndex", 0);
  2146.              this._noTagsResultsBox.collapsed = !show;
  2147.            }
  2148.            else if (type == "bookmarks") {
  2149.              
  2150.              var deck = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-bookmarks-deck");
  2151.              deck.setAttribute("selectedIndex", index);
  2152.              this._noBookmarksResultsBox.firstChild.setAttribute("selectedIndex", 0);
  2153.              this._noBookmarksResultsBox.collapsed = !show;
  2154.            }
  2155.  
  2156.        ]]></body>
  2157.       </method>
  2158.  
  2159.       <method name="_showEmptyPane">
  2160.         <parameter name="type"/>     
  2161.         <body><![CDATA[         
  2162.            
  2163.            var index = 1;
  2164.            if (type == "tags") {
  2165.              
  2166.              var deck = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-tags-deck");
  2167.              deck.setAttribute("selectedIndex", index);
  2168.              this._noTagsResultsBox.firstChild.setAttribute("selectedIndex", 1);
  2169.              this._noTagsResultsBox.collapsed = false;
  2170.            }
  2171.            else if (type == "bookmarks") {
  2172.              
  2173.              var deck = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-bookmarks-deck");
  2174.              deck.setAttribute("selectedIndex", index);
  2175.              this._noBookmarksResultsBox.firstChild.setAttribute("selectedIndex", 1);
  2176.              this._noBookmarksResultsBox.collapsed = false;
  2177.            }
  2178.  
  2179.        ]]></body>
  2180.       </method>
  2181.   
  2182.  
  2183.       <method name="_showImportingPane">
  2184.         <parameter name="type"/>     
  2185.         <body><![CDATA[         
  2186.            
  2187.            var index = 1;
  2188.            if (type == "tags") {
  2189.              
  2190.              var deck = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-tags-deck");
  2191.              deck.setAttribute("selectedIndex", index);
  2192.              this._noTagsResultsBox.firstChild.setAttribute("selectedIndex", 2);
  2193.              this._noTagsResultsBox.collapsed = false;
  2194.            }
  2195.            else if (type == "bookmarks") {
  2196.              
  2197.              var deck = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-bookmarks-deck");
  2198.              deck.setAttribute("selectedIndex", index);
  2199.              this._noBookmarksResultsBox.firstChild.setAttribute("selectedIndex", 2);
  2200.              this._noBookmarksResultsBox.collapsed = false;
  2201.            }
  2202.  
  2203.        ]]></body>
  2204.       </method>
  2205.  
  2206.     
  2207.       <method name="_searchWeb">
  2208.         <parameter name="engine"/>     
  2209.         <body><![CDATA[
  2210.         
  2211.            var url;
  2212.            if (engine == "yahoo")
  2213.              url = "http://search.yahoo.com/search?p=" + encodeURIComponent( this._searchBox.value ) + "&ei=UTF-8"; 
  2214.            else 
  2215.              url = deliciousService.getSearchUrl(this._searchBox.value);   
  2216.            openUILinkIn ( url, "current");
  2217.            this._shouldClosePopup(false);
  2218.            
  2219.        ]]></body>       
  2220.       </method>
  2221.  
  2222.      <method name="_getTree">
  2223.        <parameter name="aElement"/>
  2224.          <body><![CDATA[
  2225.          
  2226.        var parentNode = aElement;
  2227.        var elementName;
  2228.        while (parentNode) {
  2229.          
  2230.          elementName = parentNode.nodeName;
  2231.          if (elementName == "tree" || elementName == "xul:tree") {
  2232.            
  2233.            return parentNode;
  2234.          }
  2235.            
  2236.          parentNode = parentNode.parentNode;
  2237.        }
  2238.        
  2239.        return null;
  2240.          ]]></body>
  2241.      </method>
  2242.  
  2243.      <method name="_changeOpenState">
  2244.         <parameter name="tree"/>
  2245.         <parameter name="row"/>
  2246.         <parameter name="openState"/>
  2247.         <body><![CDATA[
  2248.             if (row < 0 || !tree.view.isContainer(row)) {
  2249.                 return false;
  2250.             }
  2251.             if (tree.view.isContainerOpen(row) != openState) {
  2252.                 tree.view.toggleOpenState(row);
  2253.                 if (row == tree.currentIndex) {
  2254.                     var event = document.createEvent('Events');
  2255.                     event.initEvent('OpenStateChange', true, true);
  2256.                     tree.dispatchEvent(event);
  2257.                 }
  2258.                 return true;
  2259.             }
  2260.             return false;
  2261.         ]]></body>
  2262.      </method>
  2263.  
  2264.      <method name="_shouldClosePopup">
  2265.      <parameter name="delay"/>     
  2266.        <body><![CDATA[         
  2267.           
  2268.           try{
  2269.             if (this.parentNode.nodeName == "popup") {
  2270.               if (delay) {
  2271.                 setTimeout(function(popup) { popup.hidePopup(); window.document.popupNode = null; }, 250, this.parentNode);
  2272.               }
  2273.               else {
  2274.                 setTimeout(function(popup) { popup.hidePopup(); window.document.popupNode = null; }, 0, this.parentNode);
  2275.               }  
  2276.             }
  2277.           }
  2278.           catch(e){}
  2279.           
  2280.        ]]></body>
  2281.       </method>
  2282.         
  2283.         <method name="_isCurrentLivemark">
  2284.              <parameter name="tree"/>     
  2285.        <body><![CDATA[
  2286.                   var row = tree.currentIndex;
  2287.                     var col = tree.columns.getNamedColumn('Name');
  2288.              
  2289.             var props = Components.classes["@mozilla.org/supports-array;1"].
  2290.                                createInstance(Components.interfaces.nsISupportsArray);
  2291.                     tree.view.getCellProperties(row, col, props);
  2292.                     var as = Components.classes["@mozilla.org/atom-service;1"].
  2293.                                   getService(Components.interfaces.nsIAtomService);
  2294.                     var livemarkAtom = as.getAtom("livemark");
  2295.         
  2296.                     for (var i=0; i < props.Count(); i ++) {
  2297.                         var p = props.GetElementAt(i);
  2298.                           if (livemarkAtom.equals(p)) {
  2299.                               return true;
  2300.                           }
  2301.                     }
  2302.                     return false;   
  2303.        ]]></body>
  2304.       </method>
  2305.       
  2306.       <method name="_getTreeRef">
  2307.         <parameter name="type"/>
  2308.           <body><![CDATA[
  2309.  
  2310.             var threshold = this.DEFAULT_BOOKMARKS_THRESHOLD;
  2311.         try {
  2312.           threshold = this._prefs.getIntPref( "extensions.ybookmarks@yahoo.bookmark.threshold" );
  2313.         } catch ( e ) {
  2314.         }
  2315.  
  2316.         if ( this.bookmarksStore.getTotalBookmarks() > threshold ) {
  2317.             
  2318.               return "";
  2319.             }
  2320.             else {
  2321.               if (type == "tags") {
  2322.                   return this.yTreeTagOriginalRef;
  2323.               }
  2324.               else {
  2325.               return this.yTreeBmOriginalRef;
  2326.               }
  2327.             }
  2328.           
  2329.           ]]></body>
  2330.       </method>
  2331.       
  2332.       <method name="openItemOnEnter">
  2333.         <parameter name="aEvent"/>
  2334.         <parameter name="aTree"/>
  2335.         <body><![CDATA[
  2336.           var browserTarget = whereToOpenLink(aEvent);
  2337.           this._openURLIn( aEvent, aTree, browserTarget );
  2338.           //hack
  2339.           if(!this._pinned) {
  2340.               this._canCloseSideBar = true;
  2341.               this.sidebarBlur();
  2342.           }
  2343.         ]]></body>
  2344.       </method>
  2345.       
  2346.       <method name="openItemClick">
  2347.         <parameter name="aEvent"/>
  2348.         <parameter name="aTree"/>
  2349.         <body><![CDATA[
  2350.           var row = {}, col = {}, childElt = {};
  2351.  
  2352.           this.bookmarksTreeView.treebox.getCellAt(aEvent.clientX,
  2353.                                                    aEvent.clientY,
  2354.                                                    row, col, childElt);
  2355.                                                    
  2356.           yDebug.print("openItemClick: childElt.value = \"" + childElt.value + "\"; row.value = " + row.value);
  2357.           
  2358.           if ((row.value == -1) || (col.value == null)) {
  2359.              return;
  2360.           }
  2361.            
  2362.           if ("twisty" === childElt.value) return true;
  2363.           var browserTarget = whereToOpenLink(aEvent);
  2364.           this._openURLIn( aEvent, aTree, browserTarget );
  2365.           //hack
  2366.           if(!this._pinned) {
  2367.               this._canCloseSideBar = true;
  2368.               this.sidebarBlur();
  2369.           }
  2370.         ]]></body>
  2371.       </method>
  2372.  
  2373.             <method name="_onSearchKeyUp">
  2374.         <parameter name="aEvent"/>
  2375.         <body><![CDATA[
  2376.                     switch(aEvent.keyCode) {
  2377.                   case aEvent.DOM_VK_DOWN:
  2378.                       var sidebar = aEvent.target.parentNode.parentNode.parentNode.parentNode;
  2379.                                 if (sidebar._noBookmarksResultsBox.collapsed) {
  2380.                             var bookmarksTree = sidebar.bookmarksTree;
  2381.                                     bookmarksTree.view.selection.select(0);
  2382.                                     bookmarksTree.focus();
  2383.                         aEvent.preventDefault();
  2384.                                  }
  2385.                  break;
  2386.                         default:
  2387.                      }
  2388.         ]]></body>
  2389.       </method>
  2390.             
  2391.             <method name="_onSortSelect">
  2392.               <parameter name="aEvent"/>
  2393.         <body><![CDATA[
  2394.                   var menu = aEvent.target;
  2395.                   var pref;
  2396.                       if (menu == this.bookmarksSortMenu) {
  2397.                         pref = "extensions.ybookmarks@yahoo.sidebar.bookmarksSortSelectedIndex";
  2398.                       } else if (menu == this.tagsSortMenu) {
  2399.                       pref = "extensions.ybookmarks@yahoo.sidebar.tagsSortSelectedIndex";
  2400.                     }
  2401.   
  2402.                     if (pref) {
  2403.                       var index = menu.selectedIndex;
  2404.                         this._prefs.setIntPref(pref, index);
  2405.                     }
  2406.         ]]></body>
  2407.             </method>
  2408.             
  2409.       <method name="lineWrapIntoVbox">
  2410.         <parameter name="vbox" />
  2411.         <parameter name="contentText" />
  2412.         <body><![CDATA[
  2413.         try {
  2414. //yDebug.print("ybSidebarOverlay.xml::lineWrapIntoVbox():: Coming ", YB_LOG_MESSAGE);
  2415.           /* 
  2416.            * Yes, it's lame that XUL won't allow us to have a
  2417.            * multi-line text field, so we have to resort to doing our
  2418.            * own word wrapping and putting each line in a separate
  2419.            * <xul:label>
  2420.            * (See http://blogs.acceleration.net/ryan/archive/2004/09/23/310.aspx)
  2421.            */             
  2422.           ybookmarksUtils.removeAllChildren(vbox);             
  2423.         
  2424.  
  2425.           if (contentText.length > 0) {
  2426.               var arrLines = ybookmarksUtils.lineWrap(contentText, 31);
  2427.               for (var i = 0; i < arrLines.length; i++) {
  2428.                   var lbl = document.createElement("label");
  2429.                   lbl.setAttribute("value", arrLines[i]);
  2430.                   vbox.appendChild(lbl);
  2431.               }
  2432.           }
  2433.         } catch(e) {
  2434.           yDebug.print("ybSidebarOverlay.xml::lineWrapIntoVbox():: Exception - "+e, YB_LOG_MESSAGE);
  2435.         }
  2436.         ]]></body>  
  2437.       </method>
  2438.  
  2439.       <method name="processClick">
  2440.         <parameter name="event" />
  2441.         <body><![CDATA[
  2442.  
  2443.          //do below only if the parentNode is popup
  2444.          if (this.parentNode.nodeName != "popup") {
  2445.            return;
  2446.          }
  2447.  
  2448.          var tree = this._getTree(event.originalTarget);
  2449.          if (!tree) {
  2450.            return;
  2451.          }
  2452.  
  2453.          var topContainer = document.getAnonymousElementByAttribute(this, "anonid", "ybsidebar-topContainer");
  2454.  
  2455.          //hack : the X, Y coordinate doesn't display properly,
  2456.          //we need the X Y from the browser window, not from the tree or popup 
  2457.          var posX;
  2458.          var posY;
  2459.          
  2460.            event.stopPropagation();
  2461.            event.preventDefault();
  2462.          
  2463.            posX = this.boxObject.x + event.clientX;
  2464.            if (tree == this.tagsTree) {
  2465.              posY = this.boxObject.y + event.clientY + topContainer.boxObject.height + this._tagsLabelContainer.boxObject.height;
  2466.            }
  2467.            else {
  2468.              posY = this.boxObject.y + event.clientY + topContainer.boxObject.height + 
  2469.              this.tagsTree.parentNode.parentNode.boxObject.height + this._splitter.boxObject.height + 
  2470.              this._bookmarksLabelContainer.boxObject.height;       
  2471.            }
  2472.  
  2473.            var row = { }, col = { }, obj = { };    
  2474.            var treeBoxObj = tree.treeBoxObject;
  2475.            treeBoxObj.getCellAt(posX, posY, row, col, obj);
  2476.            if ((row.value == -1) || (col.value == null)) {
  2477.              return;
  2478.            }
  2479.            //don't change the container's open state if it is a right click
  2480.            if (event.button != 2) {
  2481.                 tree.view.selection.select(row.value);
  2482.                 tree.view.selection.currentIndex = row.value;
  2483.                 if (obj.value == "twisty" || tree.view.isContainer(row.value)) {
  2484.                     this._changeOpenState(tree, row.value, !tree.view.isContainerOpen(row.value));
  2485.                 } else {
  2486.                     this._openURLIn( event, tree, 'current');
  2487.                 }
  2488.            }
  2489.         ]]></body>  
  2490.       </method>
  2491.  
  2492.       <method name="setPopupShowing">
  2493.         <parameter name="flag"/>
  2494.         <body>
  2495.             <![CDATA[            
  2496.             
  2497.             this._popupShowing = (flag == true);
  2498.             
  2499.             ]]>
  2500.         </body>
  2501.       </method>
  2502.       
  2503.      </implementation>    
  2504.  
  2505.     <handlers>
  2506.       <handler event="keypress" keycode="VK_ESCAPE" group="system">
  2507.  
  2508.          if (this.parentNode.nodeName != "popup")
  2509.            return;
  2510.          
  2511.          try {
  2512.           this.parentNode.hidePopup();
  2513.          }
  2514.          catch(e) {}
  2515.  
  2516.       </handler>
  2517.  
  2518.       <!-- Hack to prevent ctrl-b from changing the menulist. Ctrl-b is mapped to toggle sidebar -->
  2519.       <handler event="keypress" charcode="b" modifiers="control" phase="capturing">
  2520.             event.stopPropagation();
  2521.       </handler>
  2522.  
  2523.       <!-- Handles tooltip --> 
  2524.       <handler event="popupshowing" phase="capturing"><![CDATA[
  2525.       try {
  2526.       if ("xul:tooltip" !== event.originalTarget.nodeName) return true;
  2527.  
  2528.               var row = {}, col = {}, childElt = {};
  2529.     
  2530.               this.bookmarksTree.treeBoxObject.getCellAt(event.clientX - event.target.boxObject.x,
  2531.                                                         event.clientY - event.target.boxObject.y,
  2532.                                                         row, col, childElt);
  2533.     
  2534.           if (col && col.value) {
  2535.               col = col.value;
  2536.               if ("Name" === col.id) {              
  2537.                 if (row) row = row.value;
  2538.                 if (row >= 0 && row < this.bookmarksTreeView.rowCount) {
  2539.                   var name = this.bookmarksTreeView.table[row].Name;                  
  2540.                     this.lineWrapIntoVbox(document.getElementById("ybBookmarkTooltipLabel"), name);
  2541.                     return true;
  2542.                   }                
  2543.               } else if ("note" === col.id) {                  
  2544.                   if (row) row = row.value;                  
  2545.                   if (row >= 0 && row < this.bookmarksTreeView.rowCount) {
  2546.                       var desc = this.bookmarksTreeView.table[row].desc;
  2547.                       if (desc) {
  2548.                           this.lineWrapIntoVbox(document.getElementById("ybBookmarkTooltipLabel"), desc);
  2549.                           return true;
  2550.                       }
  2551.                   }
  2552.               }
  2553.           }
  2554.           event.preventDefault();
  2555.        } catch(e) {
  2556.          yDebug.print("ybSidebarOverlay.xml::handler::popupshowing::exception: "+e, YB_LOG_MESSAGE);
  2557.        }
  2558.        ]]></handler>
  2559.       
  2560.       <handler event="mousemove" phase="capturing"><![CDATA[
  2561.       try {
  2562.       if(ybookmarksUtils.getFFMajorVersion() > 2) {
  2563.               var row = {}, col = {}, childElt = {};
  2564.     
  2565.               this.bookmarksTree.treeBoxObject.getCellAt(event.clientX - event.target.boxObject.x,
  2566.                                                         event.clientY - event.target.boxObject.y,
  2567.                                                         row, col, childElt);
  2568.  
  2569.               if (col && col.value) {
  2570.                   col = col.value;
  2571.                   if ("Name" === col.id) {              
  2572.                     if (row) row = row.value;
  2573.                     if (row >= 0 && row < this.bookmarksTreeView.rowCount) {
  2574.                       var name = this.bookmarksTreeView.table[row].Name;                  
  2575.                         this.lineWrapIntoVbox(document.getElementById("ybBookmarkTooltipLabel"), name);
  2576.                         return true;
  2577.                       }                
  2578.                   } else if ("note" === col.id) {                  
  2579.                       if (row) row = row.value;                  
  2580.                       if (row >= 0 && row < this.bookmarksTreeView.rowCount) {
  2581.                           var desc = this.bookmarksTreeView.table[row].desc;
  2582.                           if (desc) {
  2583.                               this.lineWrapIntoVbox(document.getElementById("ybBookmarkTooltipLabel"), desc);
  2584.                               return true;
  2585.                           }
  2586.                       }
  2587.                   }
  2588.               }
  2589.           }
  2590.           event.preventDefault();
  2591.        } catch(e) {
  2592.          yDebug.print("ybSidebarOverlay.xml::handler::popupshowing::exception: "+e, YB_LOG_MESSAGE);
  2593.        }
  2594.        ]]></handler>
  2595.        
  2596.       <handler event="click" phase="capturing"><![CDATA[
  2597.  
  2598.          this.processClick(event);
  2599.                 
  2600.       ]]></handler>
  2601.       
  2602.     </handlers>
  2603.      
  2604.      <content>
  2605.       <xul:stringbundle src="chrome://ybookmarks/locale/ybookmarks.properties"
  2606.                         anonid="ybsidebar-stringbundle"/>
  2607.  
  2608.       <xul:tooltip id="ybBookmarkTooltip">
  2609.         <xul:vbox id="ybBookmarkTooltipLabel" width="180px" />
  2610.       </xul:tooltip>
  2611.      
  2612.       <xul:popup id="ybContextMenu"
  2613.               onpopupshowing="return _createContextMenu(event);"
  2614.               onpopuphidden ="_shouldClosePopup(false);">
  2615.           <xul:menuitem label="&ybcontextmenu.openInWindow.label;" anonid="ybContextMenu-open-in-window" 
  2616.               accesskey="&ybcontextmenu.openInWindow.accesskey;" default="true"
  2617.               oncommand="_openURLIn(event, document.popupNode.parentNode, 'current');"/>
  2618.           <xul:menuitem label="&ybcontextmenu.openInNewWindow.label;" anonid="ybContextMenu-open-in-new-window"
  2619.               accesskey="&ybcontextmenu.openInNewWindow.accesskey;"
  2620.               oncommand="_openURLIn(event, document.popupNode.parentNode, 'window');"/>  
  2621.           <xul:menuitem label="&ybcontextmenu.openInNewTab.label;" anonid="ybContextMenu-open-in-new-tab"
  2622.               accesskey="&ybcontextmenu.openInNewTab.accesskey;"
  2623.               oncommand="_openURLIn(event, document.popupNode.parentNode, 'tab');"/>
  2624.           <xul:menuseparator anonid="ybContextMenu-separator1"/>
  2625.           <xul:menuitem label="&ybcontextmenu.newBookmark.label;" anonid="ybContextMenu-new-bookmark"
  2626.               accesskey="&ybcontextmenu.newBookmark.accesskey;"
  2627.               oncommand="_newBookmark();"/>
  2628.           <xul:menuseparator anonid="ybContextMenu-separator2"/>
  2629.           <xul:menuitem label="&ybcontextmenu.deleteBookmark.label;" anonid="ybContextMenu-delete-bookmark"
  2630.               accesskey="&ybcontextmenu.deleteBookmark.accesskey;"
  2631.               oncommand="_deleteBookmark(event, document.popupNode.parentNode);"/>
  2632.           <xul:menuseparator anonid="ybContextMenu-separator3"/>
  2633.           <xul:menuitem label="&ybcontextmenu.moreAbout.label;" anonid="ybContextMenu-about"
  2634.                 accesskey="&ybcontextmenu.moreAbout.accesskey;"
  2635.                 oncommand="_moreAbout(event, document.popupNode.parentNode);"/>
  2636.           <xul:menuitem label="&ybcontextmenu.properties.label;" anonid="ybContextMenu-properties" 
  2637.               accesskey="&ybcontextmenu.properties.accesskey;"
  2638.               oncommand="_editBookmark(event, document.popupNode.parentNode);"/>      
  2639.           <xul:menuitem label="&ybcontextmenu.openTag.label;" anonid="ybContextMenu-openTag"
  2640.               accesskey="&ybcontextmenu.openTag.accesskey;"
  2641.               oncommand="_openTag(event, document.popupNode.parentNode);"/>          
  2642.           <xul:menuitem label="&ybcontextmenu.openContainer.label;" anonid="ybContextMenu-openContainer"
  2643.               accesskey="&ybcontextmenu.openContainer.accesskey;"
  2644.               oncommand="_openBookmarks(event, document.popupNode.parentNode);"/>
  2645.      </xul:popup>
  2646.     
  2647.       <xul:vbox flex="1" allowevents="true">
  2648.  
  2649.         <xul:vbox anonid="ybsidebar-topContainer" allowevents="true">
  2650.          <xul:sidebarheader align="center" anonid="ybsidebar-showSidebar" hidden="false">
  2651.            <xul:label value ="&ybsidebar.title;" flex="1" crop="end"/>          
  2652.            <xul:toolbarbutton anonid="ybsidebar-pin-button" class="yb-pin-button" tooltiptext="&ybsidebar.header.pinButttonLabel;" oncommand="togglePinState();"/>
  2653.            <!-- class tabs-closebutton is a FF style class -->
  2654.            <xul:toolbarbutton class="tabs-closebutton" tooltiptext="&ybsidebar.header.closeButtonLabel;" oncommand="ybookmarksUtils.getTopWindow().toggleSidebar('viewYBookmarksSidebar', false);"/>           
  2655.            <!--     
  2656.            <xul:toolbarbutton 
  2657.                 tooltiptext="&ybsidebar.switchToSidebar.tooltip;" 
  2658.                 class="ybsidebar-showSidebarButton"
  2659.                 oncommand="_openYBSidebar();" />
  2660.            -->     
  2661.            
  2662.          </xul:sidebarheader>
  2663.          <xul:hbox anonid="ybsidebar-searchContainer" align="center" style="padding: 0px !important;" class="ybsidebar-search">
  2664.            <xul:label value="&ybsidebar.search.label;"/>
  2665.           <!-- <xul:image class="ybsidebar-search1" /> -->
  2666.            <xul:textbox anonid="ybsidebar-search-query" flex="1000" type="timed" timeout="750"
  2667.                         class="ybsidebar-search2" 
  2668.                         oncommand="_search(this.value);" onkeyup="_onSearchKeyUp(event);" oninput="iconHandler(this.value);"/>
  2669.            <xul:toolbarbutton anonid="ybsidebar-search-reset" class="ybsidebar-search-reset-style" onmouseover="reseticonHandler('hover');" onmouseout="reseticonHandler('out');"/>
  2670.          </xul:hbox>
  2671.          <xul:hbox>
  2672.           <xul:progressmeter flex="1" mode="normal" anonid="ybsidebar-search-progress-meter" value="0" collapsed="false"/>
  2673.          </xul:hbox>
  2674.         </xul:vbox>
  2675.         
  2676.         <xul:vbox flex="1" class="ybsidebar-tree-container">
  2677.           <xul:vbox flex="1">
  2678.          <xul:hbox anonid="ybsidebar-tagsLabelContainer" class="ysidebar-label-container" align="center">
  2679.             <xul:label value="&ybsidebar.tags.label;"/>
  2680.                 <xul:hbox pack="end" flex="1" align="center">
  2681.                                     <xul:spacer flex="1000" />
  2682.                   <xul:label anonid="ybsidebar-tags-count" id="ybsidebar-tags-count" value="(##)" />
  2683.                   <xul:menulist anonid="ybsidebar-tags-sort-menu" id="ybsidebar-tags-sort-menu" label="View" flex="1" sizetopopup="none">
  2684.                     <xul:menupopup>
  2685.                       <xul:menuitem label="&ybsidebar.tags.by_alpha;" id="ybsidebar-tags-sort-menu-alpha" />
  2686.                       <xul:menuitem label="&ybsidebar.tags.by_freq;" id="ybsidebar-tags-sort-menu-freq" />
  2687.                     </xul:menupopup>
  2688.                   </xul:menulist>
  2689.                 </xul:hbox>
  2690.          </xul:hbox>
  2691.              <xul:deck  anonid="ybsidebar-tags-deck" flex="1">
  2692.                <xul:tree anonid="ybbookmarks-tree-tags" id="ybbookmarks-tree-tags" hidecolumnpicker="true" class="plain"
  2693.                          seltype="single" contextmenu="ybContextMenu" flex="1">
  2694.                  <xul:treecols>
  2695.                    <xul:treecol id="Name" sortActive="true" sortDirection="ascending" flex="10" primary="true" hideheader="true"/>
  2696.                    <xul:treecol id="NumBookmarks" flex="1" hideheader="true" align="end" pack="end" hidden="false"  class="ybSidebarTagNum"/>
  2697.                  </xul:treecols>
  2698.                  <xul:treechildren alternatingbackground="true"/>
  2699.                </xul:tree>
  2700.         
  2701.           <xul:vbox anonid="ybbookmarks-no-tags-results" 
  2702.             class="ybsidebar-no-search-result-box" 
  2703.             flex="1" collapsed="true">
  2704.              <xul:deck selectedIndex="0">
  2705.                <xul:vbox>
  2706.                  <xul:text class="ybsidebar-noSearchResultsText" value="&ybsidebar.search.noTagsFound.label;" crop="end"/>
  2707.                  <xul:spacer class="ybsidebar-spacer"/>
  2708.                  <xul:text class="ysidebar-textlink" 
  2709.                    onclick="this.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode._searchWeb('delicious');" 
  2710.                    value="&ybsidebar.search.searchDelicious.label;" crop="end"/>
  2711.                  <xul:spacer class="ybsidebar-spacer"/>
  2712.                  <xul:text class="ysidebar-textlink" 
  2713.                     onclick="this.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode._searchWeb('yahoo');" 
  2714.                     value="&ybsidebar.search.searchYahoo.label;" crop="end"/>
  2715.                </xul:vbox>
  2716.                <xul:description class="ybsidebar-searchText" crop="end">&ybsidebar.search.doSearch.label;</xul:description>
  2717.                <xul:description class="ybsidebar-importingText" crop="end">&ybsidebar.import.importing.label;</xul:description>
  2718.              </xul:deck>    
  2719.           </xul:vbox>
  2720.           
  2721.           </xul:deck>
  2722.         </xul:vbox>
  2723.         
  2724.     <xul:splitter anonid="ybsidebar-tree-splitter" />
  2725.     
  2726.           <xul:vbox flex="1">
  2727.             <xul:hbox anonid="ybsidebar-bookmarksLabelContainer" class="ysidebar-label-container" align="center">
  2728.               <xul:label value="&ybsidebar.bookmarks.label;"/>
  2729.               <xul:hbox pack="end" flex="1" align="center">
  2730.                                 <xul:spacer flex="1000" />
  2731.                 <xul:label anonid="ybsidebar-bookmarks-count" id="ybsidebar-bookmarks-count" value="(##)" />
  2732.                 <xul:menulist anonid="ybsidebar-bookmarks-sort-menu" id="ybsidebar-bookmarks-sort-menu" label="View" flex="1" sizetopopup="none">
  2733.                   <xul:menupopup>
  2734.                     <xul:menuitem label="&ybsidebar.bookmarks.by_added_date;" id="ybsidebar-bookmarks-sort-menu-last-added" />
  2735.                     <xul:menuitem label="&ybsidebar.bookmarks.by_alpha;" id="ybsidebar-bookmarks-sort-menu-alpha" />
  2736.                     <xul:menuitem label="&ybsidebar.bookmarks.by_site;" id="ybsidebar-bookmarks-sort-menu-site" />
  2737.                     <xul:menuitem label="&ybsidebar.bookmarks.by_most_visited;" id="ybsidebar-bookmarks-sort-menu-most-visited" />
  2738.                     <xul:menuitem label="&ybsidebar.bookmarks.by_last_visited;" id="ybsidebar-bookmarks-sort-menu-last-visited" />                    
  2739.                   </xul:menupopup>
  2740.                 </xul:menulist>
  2741.               </xul:hbox>
  2742.             </xul:hbox>
  2743.             <xul:deck anonid="ybsidebar-bookmarks-deck" flex="1">     
  2744.               <xul:tree anonid="ybbookmarks-tree-bookmarks" id="ybbookmarks-tree-bookmarks" hidecolumnpicker="true" class="plain"
  2745.                         onclick="if(event.button == 0){ openItemClick(event, this); }
  2746.                                  else if (event.button == 1) { _openURLIn(event, this, 'tab'); }"
  2747.                         onkeypress="if ((event.keyCode == KeyEvent.DOM_VK_RETURN) ||
  2748.                                     (event.keyCode == KeyEvent.DOM_VK_ENTER))
  2749.                                     {openItemOnEnter(event, this);}"
  2750.                         seltype="single" contextmenu="ybContextMenu" flex="1">
  2751.                 <xul:treecols>                  
  2752.                   <xul:treecol id="Name" flex="10" primary="true" hideheader="true" sortDirection="ascending" sortActive="true"/>
  2753.                   <xul:treecol id="note" flex="1" hideheader="true" align="end" pack="end" hidden="false" class="ybSidebarNotes"/>
  2754.                   <xul:treecol id="last_visited" flex="1" hideheader="true" hidden="true" />
  2755.                   <xul:treecol id="last_added" flex="1" hideheader="true" hidden="true" />                                                                                                                                
  2756.                 </xul:treecols>
  2757.                 <xul:treechildren alternatingbackground="true"  tooltip="ybBookmarkTooltip"/>
  2758.               </xul:tree>
  2759.          
  2760.           <xul:vbox anonid="ybbookmarks-no-bookmarks-results" 
  2761.             class="ybsidebar-no-search-result-box" 
  2762.             flex="1" collapsed="true">
  2763.               <xul:deck selectedIndex="0">
  2764.              <xul:vbox>
  2765.                    <xul:label class="ybsidebar-noSearchResultsText" value="&ybsidebar.search.noBookmarksFound.label;" crop="end"/>
  2766.                  </xul:vbox>
  2767.                  <xul:label class="ybsidebar-searchText" crop="end"/>
  2768.               </xul:deck>   
  2769.           </xul:vbox>
  2770.           </xul:deck>
  2771.  
  2772.         </xul:vbox>
  2773.       
  2774.       </xul:vbox>
  2775.  
  2776.         <xul:hbox anonid="ybsidebar-bottomContainer" class="ybsidebar-info-container" align="center" style="margin:0px;">
  2777.              <xul:image anonid="ybsidebar-login-image" class="ybsidebar-info-image" 
  2778.                onclick="_openHome(event);" />
  2779.                             <xul:spacer style="width:1em;"/>
  2780.                          <xul:description anonid="ybsidebar-login-status" value="(user)" style="margin: 0px;" />
  2781.              <xul:description anonid="ybsidebar-login-status-2" value="&ybsidebar.loginStatus.on;" style="margin: 0px;" />
  2782.              <xul:description anonid="ybsidebar-login-status-3" value="&ybsidebar.provider.label;" style="margin: 0px;" flex="1" crop="end"  
  2783.                               class="ysidebar-textlink" linktype="standard" onclick="_openHome(event);" />
  2784.         </xul:hbox>
  2785.  
  2786.      </xul:vbox>
  2787.     </content>    
  2788.     
  2789.   </binding>
  2790.   
  2791.   <binding id="splitter" extends="chrome://global/content/bindings/splitter.xml#splitter">
  2792.      <implementation>
  2793.        <constructor>         
  2794.          <![CDATA[
  2795.  
  2796.            this._sidebar = this.parentNode.parentNode.parentNode;
  2797.  
  2798.            this._topContainer = document.getAnonymousElementByAttribute(this._sidebar, "anonid", "ybsidebar-topContainer");
  2799.            this._bottomContainer =  document.getAnonymousElementByAttribute(this._sidebar, "anonid", "ybsidebar-bottomContainer");
  2800.            
  2801.            this.tagsTree = document.getAnonymousElementByAttribute(this._sidebar, "anonid", "ybbookmarks-tree-tags");               
  2802.            this.bookmarksTree = document.getAnonymousElementByAttribute(this._sidebar, "anonid", "ybbookmarks-tree-bookmarks");
  2803.            
  2804.            this._tagsLabelContainer = document.getAnonymousElementByAttribute(this._sidebar, "anonid", "ybsidebar-tagsLabelContainer");
  2805.            this._bookmarksLabelContainer = document.getAnonymousElementByAttribute(this._sidebar, "anonid", "ybsidebar-bookmarksLabelContainer");
  2806.            
  2807.          ]]>
  2808.       </constructor>
  2809.  
  2810.       <field name="_sidebar">null</field>
  2811.       <field name="_topContainer">null</field>
  2812.       <field name="_bottomContainer">null</field>
  2813.  
  2814.       <field name="tagsTree">null</field>
  2815.       <field name="bookmarksTree">null</field>
  2816.  
  2817.       <field name="_bookmarksLabelContainer">null</field>
  2818.       <field name="_tagsLabelContainer">null</field>
  2819.        
  2820.     </implementation>
  2821.     <handlers>
  2822.       <handler event="mousedown"><![CDATA[        
  2823.         this._startDragging = true;
  2824.       ]]></handler>
  2825.  
  2826.  
  2827.       <handler event="mouseup"><![CDATA[
  2828.         this._startDragging = false;
  2829.       ]]></handler>
  2830.  
  2831.       <handler event="mousemove"><![CDATA[
  2832.  
  2833.         //stop if mouse up
  2834.         if (!this._startDragging) {
  2835.           return;
  2836.         }  
  2837.         
  2838.         //set this for sidebar
  2839.         this._sidebar.tagsLabelContainerHeight = this._tagsLabelContainer.boxObject.height;
  2840.         
  2841.         var previousElement = this.tagsTree.parentNode.parentNode;
  2842.         var nextElement = this.bookmarksTree.parentNode.parentNode;
  2843.         
  2844.         var topExtraHeight = this._topContainer.boxObject.height + this.boxObject.height
  2845.         var topTreeHeight = event.clientY - topExtraHeight;
  2846.         var bottomExtraHeight = this._bottomContainer.boxObject.height;
  2847.         var bottomTreeHeight = this._sidebar.boxObject.height - topExtraHeight - topTreeHeight - bottomExtraHeight;
  2848.  
  2849.         //stop if the height of one of the trees is smaller than min
  2850.         var min = 20 + this._tagsLabelContainer.boxObject.height;
  2851.         if ((previousElement.boxObject.height < min   && 
  2852.             event.clientY < this._topContainer.boxObject.height) ||
  2853.             (nextElement.boxObject.height < min && 
  2854.             event.clientY > (this._topContainer.boxObject.height + previousElement.boxObject.height + this.boxObject.height)) ||
  2855.             topTreeHeight < min || 
  2856.             bottomTreeHeight < min ) {
  2857.           
  2858.           return;
  2859.         }
  2860.         
  2861.         previousElement.setAttribute("minheight", topTreeHeight);
  2862.         previousElement.setAttribute("maxheight", topTreeHeight);
  2863.         
  2864.         event.preventDefault();
  2865.         event.stopPropagation();
  2866.  
  2867.       ]]></handler>
  2868.  
  2869.     </handlers>
  2870.   
  2871.   </binding>
  2872.     
  2873. </bindings>
  2874.  
  2875. <!--
  2876. Local Variables:
  2877. mode:javascript
  2878. End:
  2879.   -->
  2880.